parameters:
  - name: testProjects
    type: object
    default:
      - OmniSharp.DotNetTest.Tests
      - OmniSharp.MSBuild.Tests,OmniSharp.Roslyn.CSharp.Tests,OmniSharp.Cake.Tests,OmniSharp.Script.Tests,OmniSharp.Stdio.Tests,OmniSharp.Http.Tests,OmniSharp.Tests,OmniSharp.Lsp.Tests

trigger:
  batch: 'true'
  branches:
    include:
      - master
      - refs/tags/*

pr:
  autoCancel: 'true'
  branches:
    include:
      - master

resources:
  repositories:
    - repository: rsg
      type: github
      name: RocketSurgeonsGuild/AzureDevopsTemplates
      ref: refs/tags/v0.4.5
      endpoint: github

variables:
  Verbosity: Diagnostic
  DotNetVersion: "3.1.401"
  CakeVersion: "0.32.1"
  NuGetVersion: "4.9.2"
  GitVersionVersion: "5.0.1"
  MonoVersion: "6.10.0"
  Coverage: "$(Agent.BuildDirectory)/c"
  VstsCoverage: "$(Coverage)"
  Artifacts: $(Build.SourcesDirectory)/artifacts/
  VstsArtifacts: "$(Artifacts)"
  DOTNET_SKIP_FIRST_TIME_EXPERIENCE: "true"

jobs:
  - job: GitVersion
    pool:
      vmImage: "windows-2019"
    steps:
      - template: gitversion/store.yml@rsg
        parameters:
          NuGetVersion: $(NuGetVersion)
          version: $(GitVersionVersion)

  - job: macOS
    pool:
      vmImage: "macOS-10.15"
    dependsOn: GitVersion
    steps:
      - template: ./.pipelines/init.yml
        parameters:
          Verbosity: $(Verbosity)
          CakeVersion: $(CakeVersion)
          DotNetVersion: $(DotNetVersion)
          NuGetVersion: $(NuGetVersion)
          MonoVersion: $(MonoVersion)
      - script: |
          echo $PATH
          chmod 755 ./build.sh
          ./build.sh --configuration Release --verbosity Verbose --target CI --publish-all --archive
        displayName: 'Build'
      - template: ./.pipelines/artifacts.yml
        parameters:
          Artifacts: $(Artifacts)

  - job: macOS_tests
    pool:
      vmImage: "macOS-10.15"
    dependsOn: GitVersion
    strategy:
      matrix:
        ${{ each project in parameters.testProjects }}:
          ${{ project }}:
            TEST_PROJECT: ${{ project }}
    steps:
      - template: ./.pipelines/init.yml
        parameters:
          Verbosity: $(Verbosity)
          CakeVersion: $(CakeVersion)
          DotNetVersion: $(DotNetVersion)
          NuGetVersion: $(NuGetVersion)
          MonoVersion: $(MonoVersion)
      - script: |
          echo $PATH
          chmod 755 ./build.sh
          ./build.sh --configuration Debug --verbosity Verbose --target Test --test-project="$TEST_PROJECT"
        displayName: 'Build'
      - template: ./.pipelines/logs.yml
        parameters:
          Artifacts: $(Artifacts)

  - job: Linux
    pool:
      vmImage: "ubuntu-18.04"
    dependsOn: GitVersion
    steps:
      - template: ./.pipelines/init.yml
        parameters:
          Verbosity: $(Verbosity)
          CakeVersion: $(CakeVersion)
          DotNetVersion: $(DotNetVersion)
          NuGetVersion: $(NuGetVersion)
          MonoVersion: $(MonoVersion)
      - script: |
          chmod 755 ./build.sh
          ./build.sh --configuration Release --verbosity Verbose --target CI --publish-all --archive
        displayName: 'Build'
      - template: ./.pipelines/artifacts.yml
        parameters:
          Artifacts: $(Artifacts)

  - job: Linux_tests
    pool:
      vmImage: "ubuntu-18.04"
    dependsOn: GitVersion
    strategy:
      matrix:
        ${{ each project in parameters.testProjects }}:
          ${{ project }}:
            TEST_PROJECT: ${{ project }}
    steps:
      - template: ./.pipelines/init.yml
        parameters:
          Verbosity: $(Verbosity)
          CakeVersion: $(CakeVersion)
          DotNetVersion: $(DotNetVersion)
          NuGetVersion: $(NuGetVersion)
          MonoVersion: $(MonoVersion)
      - script: |
          chmod 755 ./build.sh
          ./build.sh --configuration Debug --verbosity Verbose --target Test --test-project="$TEST_PROJECT"
        displayName: 'Build'
      - template: ./.pipelines/logs.yml
        parameters:
          Artifacts: $(Artifacts)

  - job: Windows
    pool:
      vmImage: "windows-2019"
    dependsOn: GitVersion
    steps:
      - template: ./.pipelines/init.yml
        parameters:
          Verbosity: $(Verbosity)
          CakeVersion: $(CakeVersion)
          DotNetVersion: $(DotNetVersion)
          NuGetVersion: $(NuGetVersion)
      - powershell: .\build.ps1 -configuration Release -verbosity Verbose -target CI -publish-all -archive
        displayName: 'Build'
      - template: ./.pipelines/artifacts.yml
        parameters:
          Artifacts: $(Artifacts)

  - job: Windows_tests
    pool:
      vmImage: "windows-2019"
    dependsOn: GitVersion
    strategy:
      matrix:
        ${{ each project in parameters.testProjects }}:
          ${{ project }}:
            TEST_PROJECT: ${{ project }}
    steps:
      - template: ./.pipelines/init.yml
        parameters:
          Verbosity: $(Verbosity)
          CakeVersion: $(CakeVersion)
          DotNetVersion: $(DotNetVersion)
          NuGetVersion: $(NuGetVersion)
      - powershell: .\build.ps1 -configuration Debug -verbosity Verbose --test-project="$ENV:TEST_PROJECT" -target Test
        displayName: 'Build'
      - template: ./.pipelines/logs.yml
        parameters:
          Artifacts: $(Artifacts)

  - job: Release
    pool:
      vmImage: "Ubuntu-16.04"
    dependsOn:
      - macOS
      - macOS_tests
      - Linux
      - Linux_tests
      - Windows
      - Windows_tests
    steps:
      - task: NuGetToolInstaller@1
        displayName: 'Install NuGet'
        inputs:
          versionSpec: $(NuGetVersion)
      - task: DownloadBuildArtifacts@0
        displayName: Download Packages
        inputs:
          downloadType: 'single'
          artifactName: 'packages'
          buildType: 'current'
          downloadPath: '$(System.ArtifactsDirectory)'
      - task: DownloadBuildArtifacts@0
        displayName: Download Deployment
        inputs:
          downloadType: 'single'
          artifactName: 'deployment'
          buildType: 'current'
          downloadPath: '$(System.ArtifactsDirectory)'
      - task: DownloadBuildArtifacts@0
        displayName: Download NuGet
        inputs:
          downloadType: 'single'
          artifactName: 'nuget'
          buildType: 'current'
          downloadPath: '$(System.ArtifactsDirectory)'
      - task: NuGetCommand@2
        displayName: 'Push NuGet packages to myget.org'
        inputs:
          command: push
          nuGetFeedType: external
          packagesToPush: '$(System.ArtifactsDirectory)/nuget/**/*.nupkg'
          publishFeedCredentials: myget.org
        condition: and(succeeded(), or(startsWith(variables['Build.SourceBranch'], 'refs/tags/v'), eq(variables['Build.SourceBranch'], 'refs/heads/master')))
      - task: NuGetCommand@2
        displayName: 'Push NuGet packages to nuget.org'
        inputs:
          command: push
          nuGetFeedType: external
          packagesToPush: '$(System.ArtifactsDirectory)/nuget/**/*.nupkg'
          publishFeedCredentials: nuget.org
        condition: and(succeeded(), startsWith(variables['Build.SourceBranch'], 'refs/tags/v'))
      - script: |
          AZ_REPO=$(lsb_release -cs)
          echo "deb [arch=amd64] https://packages.microsoft.com/repos/azure-cli/ $AZ_REPO main" | \
            sudo tee /etc/apt/sources.list.d/azure-cli.list
          curl -L https://packages.microsoft.com/keys/microsoft.asc | sudo apt-key add -
          sudo apt-get install apt-transport-https
          sudo apt-get update && sudo apt-get install azure-cli
          az storage blob upload-batch --destination "releases" --source "$(System.ArtifactsDirectory)/deployment/" --account-name roslynomnisharp --account-key $BLOB_KEY
        displayName: Upload to Azure Storage
        condition: and(succeeded(), eq(variables['Build.SourceBranch'], 'refs/heads/master'))
        env:
          BLOB_KEY: $(BLOB_KEY)
      - task: GitHubRelease@0
        displayName: 'GitHub release (edit)'
        condition: and(succeeded(), startsWith(variables['Build.SourceBranch'], 'refs/tags/v'))
        inputs:
          gitHubConnection: github
          repositoryName: OmniSharp/omnisharp-roslyn
          action: edit
          tag: '$(Build.SourceBranchName)'
          title: '$(Build.SourceBranchName)'
          assets: '$(System.ArtifactsDirectory)/packages/**/*'
          assetUploadMode: replace
          # releaseNotesSource: input
          # releaseNotes: asdfasdf12
          # isDraft: true
          # isPreRelease: true
          # addChangeLog: false

{'repo_name': 'OmniSharp/omnisharp-roslyn', 'stars': '895', 'repo_language': 'C#', 'file_name': 'Using-Omnisharp.md', 'mime_type': 'text/plain', 'hash': 8056059926447215230, 'source_dataset': 'data'}


如果您在腾讯云中使用到了云数据库、云服务器、私有网络等服务，这些服务由不同的人管理，但都共享您的云账号密钥，将存在以下问题：
- 您的密钥由多人共享，泄密风险高。
- 您无法限制他人的访问权限，易产生误操作造成安全风险。

这个时候，访问管理应运而生。
有关腾讯云访问管理 CAM 的更多介绍，请参见 [CAM 概述](https://cloud.tencent.com/document/product/598/10583)。

接入CAM 后，可通过子账号实现不同的人管理不同的服务，以避免出现以上的问题。默认情况下，子账号没有使用云数据库实例以及云数据库相关资源的权限。因此，我们就需要创建策略来允许子账号使用他们所需要的资源或者权限。

策略是定义和描述一条或多条权限的语法规范，策略通过授权一个用户或者一组用户来允许或拒绝使用指定资源。CAM 策略的更多基本信息请参见 [策略语法](https://cloud.tencent.com/document/product/598/10603)，使用信息请参见 [策略](https://cloud.tencent.com/document/product/598/10601)。

如果您不需要对子账户进行云数据库相关资源的访问管理，您可以跳过此章节。跳过这些部分并不影响您对文档中其余部分的理解和使用。

### 入门
CAM 策略必须授权使用一个或多个云数据库操作或者必须拒绝使用一个或多个云数据库操作。同时还必须指定可以用于操作的资源（可以是全部资源，某些操作也可以是部分资源），策略还可以包含操作资源所设置的条件。

>!
> - 建议用户使用 CAM 策略来管理云数据库资源和授权云数据库操作，对于存量分项目权限的用户体验不变，但不建议再继续使用分项目权限来管理资源与授权操作。
> - 云数据库暂时不支持相关生效条件设置。

{'repo_name': 'tencentyun/qcloud-documents', 'stars': '773', 'repo_language': 'HTML', 'file_name': '发单聊消息之前回调.md', 'mime_type': 'text/plain', 'hash': -7009575725416526670, 'source_dataset': 'data'}


#
#  Parameters for the Streitz and Mintmire variable charge model for alumina
#
#  Phys. Rev. B, 50, 11996 (1994)
#
keyword sm
smelectronegativity
Al 0.000000 5.164327 0.968438 0.746759
O  5.484763 7.017857 2.143957 0.000000
buck
Al core Al core    4.474755 0.991317 0.0 0.0 12.0
Al core O  core   62.933909 0.443658 0.0 0.0 12.0
O  core O  core 3322.784218 0.291065 0.0 0.0 12.0
rydberg
Al core Al core 0.159472  5.949143672000 3.365875 0.0 12.0
Al core O  core 0.094594  9.985407051900 2.358570 0.0 12.0
O  core O  core 1.865072 16.822405075464 2.005092 0.0 12.0
manybody
Al core Al core  0.0 8.0
Al core O  core  0.0 8.0
O  core O  core  0.0 8.0
eam_functional square_root
Al core 1.987699
O  core 2.116850
eam_density exponential 0
Al core 0.147699 2.017519 3.365875
O  core 1.000000 6.871329 2.005092

{'repo_name': 'materialsproject/pymatgen', 'stars': '596', 'repo_language': 'Python', 'file_name': '__init__.py', 'mime_type': 'text/plain', 'hash': 6673412974860233527, 'source_dataset': 'data'}


/* SPDX-License-Identifier: GPL-2.0 */
/* X-SPDX-Copyright-Text: (c) Solarflare Communications Inc */
#ifndef __ONLOAD_MMAP_H__
#define __ONLOAD_MMAP_H__

/* For CI_CFG_* */
#include <ci/internal/transport_config_opt.h>
#include <onload/mmap_base.h>
#include <cplane/mmap.h>

/* OO_MMAP_TYPE_NETIF offsets has following IDs:
 * - CI_NETIF_MMAP_ID_STATE     netif shared state; ep buffers
 * - CI_NETIF_MMAP_ID_TIMESYNC  timesync shared state, read-only
 *                              (could be extended to other global shared
 *                              states)
 * - CI_NETIF_MMAP_ID_IO        VI resource: IO bar.
 * - CI_NETIF_MMAP_ID_IOBUFS    VI resource: queues
 *   + if CI_CFG_PKTS_AS_HUGE_PAGES=1, mmap pkt_shm_id array
 * - CI_NETIF_MMAP_ID_PIO       VI resource: PIO IO BAR
 * - CI_NETIF_MMAP_ID_CTPIO     VI resource: CTPIO IO BAR
 * - CI_NETIF_MMAP_ID_OFE_RO    OFE read-only part of engine
 * - CI_NETIF_MMAP_ID_OFE_RW    OFE read-write part of engine
 * - CI_NETIF_MMAP_ID_CPLANE    Control plame MIBs mapping
 * - CI_NETIF_MMAP_ID_PKTS + packet set id
 *   packet sets
 */
#define CI_NETIF_MMAP_ID_STATE    0
#define CI_NETIF_MMAP_ID_TIMESYNC 1
#define CI_NETIF_MMAP_ID_IO       2
#define CI_NETIF_MMAP_ID_IOBUFS   3
#if CI_CFG_PIO
#define CI_NETIF_MMAP_ID_PIO      4
#endif
#if CI_CFG_CTPIO
#define CI_NETIF_MMAP_ID_CTPIO    5
#endif
#ifdef ONLOAD_OFE
#define CI_NETIF_MMAP_ID_OFE_RO   6
#define CI_NETIF_MMAP_ID_OFE_RW   7
#endif
#define CI_NETIF_MMAP_ID_PKTS     8
#define CI_NETIF_MMAP_ID_PKTSET(id) (CI_NETIF_MMAP_ID_PKTS+(id))

/* OO_MMAP_TYPE_DSHM:
 * "Donation" shm mmap IDs encode buffer ID and class. */
#ifdef OO_MMAP_TYPE_DSHM
# define OO_MMAP_DSHM_BUFFER_ID_WIDTH 32
# define OO_MMAP_DSHM_SHM_CLASS_WIDTH 12
# define OO_MMAP_DSHM_BUFFER_ID(map_id) \
    ((map_id) & ((1ull << OO_MMAP_DSHM_BUFFER_ID_WIDTH) - 1))
# define OO_MMAP_DSHM_SHM_CLASS(map_id) \
    (((map_id) >> OO_MMAP_DSHM_BUFFER_ID_WIDTH) & \
     ((1ull << OO_MMAP_DSHM_SHM_CLASS_WIDTH) - 1))
# define OO_MMAP_DSHM_MAKE_ID(shm_class, buffer_id) \
    ((ci_uint64) (buffer_id) | \
     ((ci_uint64) (shm_class) << OO_MMAP_DSHM_BUFFER_ID_WIDTH))
#endif

#define VMA_OFFSET(vma)  ((vma)->vm_pgoff << PAGE_SHIFT)

#endif

{'repo_name': 'majek/openonload', 'stars': '150', 'repo_language': 'C', 'file_name': 'efthrm.mk', 'mime_type': 'text/plain', 'hash': -5927409890916992470, 'source_dataset': 'data'}


/*
* This file is based on the Windows Pointer Input Message support code files by
* Alvin Wong.
* Notwithstanding the license specified in this repository, this file is
* redistributed under BSD 2-Clause license written below in order to keep
* backporting available.
*
* All contributions by Alvin Wong:
* Copyright (c) 2017 Alvin Wong <alvinhochun@gmail.com>
* All rights reserved.
*
* All other contributions:
* Copyright (c) 2018, the respective contributors.
* All rights reserved.
*
* Each contributor holds copyright over their respective contributions.
* The project versioning (Git) records all such contribution source information.
*
* 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 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.
*/

// Get Windows 8 API prototypes and types
#ifdef WINVER
#undef WINVER
#endif
#ifdef _WIN32_WINNT
#undef _WIN32_WINNT
#endif
#define WINVER 0x0602
#define _WIN32_WINNT 0x0602

#include "kis_tablet_support_win8.h"

#include <QApplication>
#include <QDebug>
#include <QHash>
#include <QLibrary>
#include <QPointer>
#include <QTabletEvent>
#include <QVector>
#include <QWidget>
#include <QWindow>

#include <utility>

#ifdef _WIN32

#ifdef KRITA
#include <kis_debug.h>
#endif

#include <windows.h>
#include <tpcshrd.h>

#ifndef Q_OS_WIN
#error This file must not be compiled for non-Windows systems
#endif

namespace {

class Win8PointerInputApi {
#define WIN8_POINTER_INPUT_API_LIST(FUNC)                                      \
  /* Pointer Input Functions */                                                \
  FUNC(GetPointerPenInfo)                                                      \
  FUNC(GetPointerPenInfoHistory)                                               \
  FUNC(GetPointerType)                                                         \
  /* Pointer Device Functions */                                               \
  FUNC(GetPointerDevices)                                                      \
  /*FUNC(GetPointerDeviceProperties)*/                                         \
  FUNC(GetPointerDevice)                                                       \
  FUNC(GetPointerDeviceRects)                                                  \
  /*FUNC(RegisterPointerDeviceNotifications)*/                                 \
  /* end */

  bool m_loaded;

public:
#define DEFINE_FP_FROM_WINAPI(func)                                            \
  \
public:                                                                        \
  using p##func##_t = std::add_pointer<decltype(func)>::type;                  \
  \
private:                                                                       \
  p##func##_t m_p##func = nullptr;                                             \
  \
public:                                                                        \
  const p##func##_t &func = m_p##func;  // const fp ref to member

  WIN8_POINTER_INPUT_API_LIST(DEFINE_FP_FROM_WINAPI)

#undef DEFINE_FP_FROM_WINAPI

public:
  Win8PointerInputApi() : m_loaded(false) {}

  bool init() {
    if (m_loaded) {
      return true;
    }

    QLibrary user32Lib("user32");
    if (!user32Lib.load()) {
      qWarning() << "Failed to load user32.dll! This really should not happen.";
      return false;
    }

#ifdef KRITA
#define LOAD_AND_CHECK_FP_FROM_WINAPI(func)                                    \
  m_p##func = reinterpret_cast<p##func##_t>(user32Lib.resolve(#func));         \
  if (!m_p##func) {                                                            \
    dbgTablet << "Failed to load function " #func " from user32.dll";          \
    return false;                                                              \
  }
#else
#define LOAD_AND_CHECK_FP_FROM_WINAPI(func)                                    \
  m_p##func = reinterpret_cast<p##func##_t>(user32Lib.resolve(#func));         \
  if (!m_p##func) {                                                            \
    return false;                                                              \
  }
#endif

    WIN8_POINTER_INPUT_API_LIST(LOAD_AND_CHECK_FP_FROM_WINAPI)

#undef LOAD_AND_CHECK_FP_FROM_WINAPI

#ifdef KRITA
    dbgTablet << "Loaded Windows 8 Pointer Input API functions";
#endif
    m_loaded = true;
    return true;
  }

  bool isLoaded() { return m_loaded; }

#undef WIN8_POINTER_INPUT_API_LIST
};  // class Win8PointerInputApi

Win8PointerInputApi api;

class PointerFlagsWrapper {
  const POINTER_FLAGS f;

public:
  PointerFlagsWrapper(POINTER_FLAGS flags) : f(flags) {}

  static PointerFlagsWrapper fromPointerInfo(const POINTER_INFO &pointerInfo) {
    return PointerFlagsWrapper(pointerInfo.pointerFlags);
  }

  static PointerFlagsWrapper fromPenInfo(const POINTER_PEN_INFO &penInfo) {
    return fromPointerInfo(penInfo.pointerInfo);
  }

  bool isNew() const { return f & POINTER_FLAG_NEW; }

  bool isInRange() const { return f & POINTER_FLAG_INRANGE; }

  bool isInContact() const { return f & POINTER_FLAG_INCONTACT; }

  bool isFirstButtonDown() const { return f & POINTER_FLAG_FIRSTBUTTON; }

  bool isSecondButtonDown() const { return f & POINTER_FLAG_SECONDBUTTON; }

  bool isThirdButtonDown() const { return f & POINTER_FLAG_THIRDBUTTON; }

  bool isForthButtonDown() const { return f & POINTER_FLAG_FOURTHBUTTON; }

  bool isFifthButtonDown() const { return f & POINTER_FLAG_FIFTHBUTTON; }

  bool isPrimary() const { return f & POINTER_FLAG_PRIMARY; }

  bool isConfidence() const { return f & POINTER_FLAG_CONFIDENCE; }

  bool isCancelled() const { return f & POINTER_FLAG_CANCELED; }

  bool isDown() const { return f & POINTER_FLAG_DOWN; }

  bool isUpdate() const { return f & POINTER_FLAG_UPDATE; }

  bool isUp() const { return f & POINTER_FLAG_UP; }

  bool isWheel() const { return f & POINTER_FLAG_WHEEL; }

  bool isHWheel() const { return f & POINTER_FLAG_HWHEEL; }

  bool isCaptureChanged() const { return f & POINTER_FLAG_CAPTURECHANGED; }

  bool hasTransform() const {
    // mingw-w64 headers is missing this flag
    // return f & POINTER_FLAG_HASTRANSFORM;
    return f & 0x00400000;
  }
};  // class PointerFlagsWrapper

class PenFlagsWrapper {
  const PEN_FLAGS f;

public:
  PenFlagsWrapper(PEN_FLAGS flags) : f(flags) {}

  static PenFlagsWrapper fromPenInfo(const POINTER_PEN_INFO &penInfo) {
    return PenFlagsWrapper(penInfo.penFlags);
  }

  bool isBarrelPressed() const { return f & PEN_FLAG_BARREL; }

  bool isInverted() const { return f & PEN_FLAG_INVERTED; }

  bool isEraserPressed() const { return f & PEN_FLAG_ERASER; }
};  // class PenFlagsWrapper

class PenMaskWrapper {
  const PEN_MASK f;

public:
  PenMaskWrapper(PEN_MASK mask) : f(mask) {}

  static PenMaskWrapper fromPenInfo(const POINTER_PEN_INFO &penInfo) {
    return PenMaskWrapper(penInfo.penMask);
  }

  bool pressureValid() const { return f & PEN_MASK_PRESSURE; }

  bool rotationValid() const { return f & PEN_MASK_ROTATION; }

  bool tiltXValid() const { return f & PEN_MASK_TILT_X; }

  bool tiltYValid() const { return f & PEN_MASK_TILT_Y; }
};  // class PenMaskWrapper

struct PointerDeviceItem {
  // HANDLE handle;
  // RECT pointerDeviceRect;
  // RECT displayRect;
  qreal himetricToPixelX;
  qreal himetricToPixelY;
  qreal pixelOffsetX;
  qreal pixelOffsetY;
  DISPLAYCONFIG_ROTATION deviceOrientation;  // This is needed to fix tilt
};

QHash<HANDLE, PointerDeviceItem> penDevices;

struct PenPointerItem {
  // int pointerId;
  // POINTER_PEN_INFO penInfo;
  HWND hwnd;
  HANDLE deviceHandle;
  QPointer<QWidget> activeWidget;  // Current widget receiving events
  qreal oneOverDpr;                // 1 / devicePixelRatio of activeWidget
  bool widgetIsCaptured;       // Current widget is capturing a pen cown event
  bool widgetIsIgnored;        // Pen events should be ignored until pen up
  bool widgetAcceptsPenEvent;  // Whether the widget accepts pen events

  bool isCaptured() const { return widgetIsCaptured; }
};

QHash<int, PenPointerItem> penPointers;
// int primaryPenPointerId;

bool handlePointerMsg(const MSG &msg);

// extern "C" {
//
// LRESULT CALLBACK pointerDeviceNotificationsWndProc(HWND hwnd, UINT uMsg,
// WPARAM wParam, LPARAM lParam)
// {
//     switch (uMsg) {
//     case WM_POINTERDEVICECHANGE:
//         dbgTablet << "I would want to handle this WM_POINTERDEVICECHANGE
//         event, but ms just doesn't want me to use it";
//         dbgTablet << "  wParam:" << wParam;
//         dbgTablet << "  lParam:" << lParam;
//         return 0;
//     case WM_POINTERDEVICEINRANGE:
//         dbgTablet << "I would want to handle this WM_POINTERDEVICEINRANGE
//         event, but ms just doesn't want me to use it";
//         dbgTablet << "  wParam:" << wParam;
//         dbgTablet << "  lParam:" << lParam;
//         return 0;
//     case WM_POINTERDEVICEOUTOFRANGE:
//         dbgTablet << "I would want to handle this WM_POINTERDEVICEOUTOFRANGE
//         event, but ms just doesn't want me to use it";
//         dbgTablet << "  wParam:" << wParam;
//         dbgTablet << "  lParam:" << lParam;
//         return 0;
//     }
//     return DefWindowProcW(hwnd, uMsg, wParam, lParam);
// }
//
// } // extern "C"

}  // namespace

bool KisTabletSupportWin8::isAvailable() {
  // Just try loading the APIs
  return api.init();
}

bool KisTabletSupportWin8::isPenDeviceAvailable() {
  if (!api.init()) {
    return false;
  }
  UINT32 deviceCount = 0;
  if (!api.GetPointerDevices(&deviceCount, nullptr)) {
#ifdef KRITA
    dbgTablet << "GetPointerDevices failed";
#endif
    return false;
  }
  if (deviceCount == 0) {
#ifdef KRITA
    dbgTablet << "No pointer devices";
#endif
    return false;
  }
  QVector<POINTER_DEVICE_INFO> devices(deviceCount);
  if (!api.GetPointerDevices(&deviceCount, devices.data())) {
#ifdef KRITA
    dbgTablet << "GetPointerDevices failed";
#endif
    return false;
  }
  bool hasPenDevice = false;
  for (const POINTER_DEVICE_INFO &device : devices) {
#ifdef KRITA
    dbgTablet << "Found pointer device" << static_cast<void *>(device.device)
              << QString::fromWCharArray(device.productString)
              << "type:" << device.pointerDeviceType;
#endif
    if (device.pointerDeviceType == POINTER_DEVICE_TYPE_INTEGRATED_PEN ||
        device.pointerDeviceType == POINTER_DEVICE_TYPE_EXTERNAL_PEN) {
      hasPenDevice = true;
    }
  }
#ifdef KRITA
  dbgTablet << "hasPenDevice:" << hasPenDevice;
#endif
  return hasPenDevice;
}

bool KisTabletSupportWin8::init() { return api.init(); }

// void KisTabletSupportWin8::registerPointerDeviceNotifications()
// {
//     const wchar_t *className = L"w8PointerMsgWindow";
//     HINSTANCE hInst = static_cast<HINSTANCE>(GetModuleHandleW(nullptr));
//     WNDCLASSEXW wc;
//     wc.cbSize = sizeof(WNDCLASSEXW);
//     wc.style = 0;
//     wc.lpfnWndProc = pointerDeviceNotificationsWndProc;
//     wc.cbClsExtra = 0;
//     wc.cbWndExtra = 0;
//     wc.hInstance = hInst;
//     wc.hCursor = 0;
//     wc.hbrBackground = GetSysColorBrush(COLOR_WINDOW);
//     wc.hIcon = 0;
//     wc.hIconSm = 0;
//     wc.lpszMenuName = 0;
//     wc.lpszClassName = className;
//
//     if (RegisterClassEx(&wc)) {
//         HWND hwnd = CreateWindowEx(0, className, nullptr, 0, 0, 0, 0, 0,
//         HWND_MESSAGE, nullptr, hInst, nullptr);
//         api.RegisterPointerDeviceNotifications(hwnd, TRUE);
//     } else {
//         dbgTablet << "Cannot register dummy window";
//     }
// }

bool KisTabletSupportWin8::nativeEventFilter(const QByteArray &eventType,
                                             void *message, long *result) {
  if (!result) {
    // I don't know why this even happens, but it actually does
    // And the same event is sent in again with result != nullptr
    return false;
  }

  // This is only installed on Windows so there is no reason to check eventType
  MSG &msg = *static_cast<MSG *>(message);

  switch (msg.message) {
  case WM_POINTERDOWN:
  case WM_POINTERUP:
  case WM_POINTERENTER:
  case WM_POINTERLEAVE:
  case WM_POINTERUPDATE:
  case WM_POINTERCAPTURECHANGED: {
    bool handled = handlePointerMsg(msg);
    if (handled) {
      *result = 0;
      return true;
    }
    break;
  }
  case WM_TABLET_QUERYSYSTEMGESTURESTATUS:
    *result = 0;
    return true;
  }

  Q_UNUSED(eventType)
  return false;
}

namespace {

QDebug operator<<(QDebug debug, const POINT &pt) {
  QDebugStateSaver saver(debug);
  debug.nospace() << '(' << pt.x << ", " << pt.y << ')';

  return debug;
}

QDebug operator<<(QDebug debug, const RECT &rect) {
  QDebugStateSaver saver(debug);
  debug.nospace() << '(' << rect.left << ", " << rect.top << ", " << rect.right
                  << ", " << rect.bottom << ')';

  return debug;
}

bool registerOrUpdateDevice(HANDLE deviceHandle, const RECT &pointerDeviceRect,
                            const RECT &displayRect,
                            const DISPLAYCONFIG_ROTATION deviceOrientation) {
  bool isPreviouslyRegistered     = penDevices.contains(deviceHandle);
  PointerDeviceItem &deviceItem   = penDevices[deviceHandle];
  PointerDeviceItem oldDeviceItem = deviceItem;
  // deviceItem.handle = deviceHandle;
  deviceItem.himetricToPixelX =
      static_cast<qreal>(displayRect.right - displayRect.left) /
      (pointerDeviceRect.right - pointerDeviceRect.left);
  deviceItem.himetricToPixelY =
      static_cast<qreal>(displayRect.bottom - displayRect.top) /
      (pointerDeviceRect.bottom - pointerDeviceRect.top);
  deviceItem.pixelOffsetX =
      static_cast<qreal>(displayRect.left) -
      deviceItem.himetricToPixelX * pointerDeviceRect.left;
  deviceItem.pixelOffsetY = static_cast<qreal>(displayRect.top) -
                            deviceItem.himetricToPixelY * pointerDeviceRect.top;
  deviceItem.deviceOrientation = deviceOrientation;
  if (!isPreviouslyRegistered) {
#ifdef KRITA
    dbgTablet << "Registered pen device" << deviceHandle << "with displayRect"
              << displayRect << "and deviceRect" << pointerDeviceRect << "scale"
              << deviceItem.himetricToPixelX << deviceItem.himetricToPixelY
              << "offset" << deviceItem.pixelOffsetX << deviceItem.pixelOffsetY
              << "orientation" << deviceItem.deviceOrientation;
#endif
  } else if (deviceItem.himetricToPixelX != oldDeviceItem.himetricToPixelX ||
             deviceItem.himetricToPixelY != oldDeviceItem.himetricToPixelY ||
             deviceItem.pixelOffsetX != oldDeviceItem.pixelOffsetX ||
             deviceItem.pixelOffsetY != oldDeviceItem.pixelOffsetY ||
             deviceItem.deviceOrientation != oldDeviceItem.deviceOrientation) {
#ifdef KRITA
    dbgTablet << "Updated pen device" << deviceHandle << "with displayRect"
              << displayRect << "and deviceRect" << pointerDeviceRect << "scale"
              << deviceItem.himetricToPixelX << deviceItem.himetricToPixelY
              << "offset" << deviceItem.pixelOffsetX << deviceItem.pixelOffsetY
              << "orientation" << deviceItem.deviceOrientation;
#endif
  }
  return true;
}

bool registerOrUpdateDevice(HANDLE deviceHandle) {
  RECT pointerDeviceRect, displayRect;
  if (!api.GetPointerDeviceRects(deviceHandle, &pointerDeviceRect,
                                 &displayRect)) {
#ifdef KRITA
    dbgTablet << "GetPointerDeviceRects failed";
#endif
    return false;
  }
  POINTER_DEVICE_INFO pointerDeviceInfo;
  if (!api.GetPointerDevice(deviceHandle, &pointerDeviceInfo)) {
#ifdef KRITA
    dbgTablet << "GetPointerDevice failed";
#endif
    return false;
  }
  return registerOrUpdateDevice(deviceHandle, pointerDeviceRect, displayRect,
                                static_cast<DISPLAYCONFIG_ROTATION>(
                                    pointerDeviceInfo.displayOrientation));
}

QTabletEvent makeProximityTabletEvent(const QEvent::Type eventType,
                                      const POINTER_PEN_INFO &penInfo) {
  PenFlagsWrapper penFlags = PenFlagsWrapper::fromPenInfo(penInfo);
  QTabletEvent::PointerType pointerType =
      penFlags.isInverted() ? QTabletEvent::Eraser : QTabletEvent::Pen;
  const QPointF emptyPoint;
  return QTabletEvent(
      eventType,             // type
      emptyPoint,            // pos
      emptyPoint,            // globalPos
      QTabletEvent::Stylus,  // device
      pointerType,           // pointerType
      0,                     // pressure
      0,                     // xTilt
      0,                     // yTilt
      0,                     // tangentialPressure
      0,                     // rotation
      0,                     // z
      Qt::NoModifier,        // keyState
      reinterpret_cast<qint64>(penInfo.pointerInfo.sourceDevice),  // uniqueID
      Qt::NoButton,                                                // button
      (Qt::MouseButtons)0                                          // buttons
      );
}

// void rotateTiltAngles(int &tiltX, int &tiltY, const DISPLAYCONFIG_ROTATION
// orientation) {
//     int newTiltX, newTiltY;
//     switch (orientation) {
//     case DISPLAYCONFIG_ROTATION_ROTATE90:
//         newTiltX = -tiltY;
//         newTiltY = tiltX;
//         break;
//     case DISPLAYCONFIG_ROTATION_ROTATE180:
//         newTiltX = -tiltX;
//         newTiltY = -tiltY;
//         break;
//     case DISPLAYCONFIG_ROTATION_ROTATE270:
//         newTiltX = tiltY;
//         newTiltY = -tiltX;
//         break;
//     case DISPLAYCONFIG_ROTATION_IDENTITY:
//     default:
//         newTiltX = tiltX;
//         newTiltY = tiltY;
//         break;
//     }
//     tiltX = newTiltX;
//     tiltY = newTiltY;
// }

QTabletEvent makePositionalTabletEvent(const QWidget *targetWidget,
                                       const QEvent::Type eventType,
                                       const POINTER_PEN_INFO &penInfo,
                                       const PointerDeviceItem &deviceItem,
                                       const PenPointerItem &penPointerItem) {
  PenFlagsWrapper penFlags         = PenFlagsWrapper::fromPenInfo(penInfo);
  PointerFlagsWrapper pointerFlags = PointerFlagsWrapper::fromPenInfo(penInfo);
  PenMaskWrapper penMask           = PenMaskWrapper::fromPenInfo(penInfo);

  const QPointF globalPosF((deviceItem.himetricToPixelX *
                                penInfo.pointerInfo.ptHimetricLocationRaw.x +
                            deviceItem.pixelOffsetX) *
                               penPointerItem.oneOverDpr,
                           (deviceItem.himetricToPixelY *
                                penInfo.pointerInfo.ptHimetricLocationRaw.y +
                            deviceItem.pixelOffsetY) *
                               penPointerItem.oneOverDpr);
  const QPoint globalPos  = globalPosF.toPoint();
  const QPoint localPos   = targetWidget->mapFromGlobal(globalPos);
  const QPointF delta     = globalPosF - globalPos;
  const QPointF localPosF = localPos + delta;

  const QTabletEvent::PointerType pointerType =
      penFlags.isInverted() ? QTabletEvent::Eraser : QTabletEvent::Pen;

  Qt::MouseButton mouseButton;
  if (eventType == QEvent::TabletPress) {
    if (penInfo.pointerInfo.ButtonChangeType ==
        POINTER_CHANGE_SECONDBUTTON_DOWN) {
      mouseButton = Qt::RightButton;
    } else {
#ifdef KRITA
      KIS_SAFE_ASSERT_RECOVER(penInfo.pointerInfo.ButtonChangeType ==
                              POINTER_CHANGE_FIRSTBUTTON_DOWN) {
#else
      if (!(penInfo.pointerInfo.ButtonChangeType ==
            POINTER_CHANGE_FIRSTBUTTON_DOWN)) {
#endif
        qWarning() << "WM_POINTER* sent unknown ButtonChangeType"
                   << penInfo.pointerInfo.ButtonChangeType;
      }
      mouseButton = Qt::LeftButton;
    }
  } else if (eventType == QEvent::TabletRelease) {
    if (penInfo.pointerInfo.ButtonChangeType ==
        POINTER_CHANGE_SECONDBUTTON_UP) {
      mouseButton = Qt::RightButton;
    } else {
#ifdef KRITA
      KIS_SAFE_ASSERT_RECOVER(penInfo.pointerInfo.ButtonChangeType ==
                              POINTER_CHANGE_FIRSTBUTTON_UP) {
#else
      if (!(penInfo.pointerInfo.ButtonChangeType ==
            POINTER_CHANGE_FIRSTBUTTON_UP)) {
#endif
        qWarning() << "WM_POINTER* sent unknown ButtonChangeType"
                   << penInfo.pointerInfo.ButtonChangeType;
      }
      mouseButton = Qt::LeftButton;
    }
  } else {
    mouseButton = Qt::NoButton;
  }

  Qt::MouseButtons mouseButtons;
  if (pointerFlags.isFirstButtonDown()) {
    mouseButtons |= Qt::LeftButton;
  }
  if (pointerFlags.isSecondButtonDown()) {
    mouseButtons |= Qt::RightButton;
  }

  int tiltX = 0, tiltY = 0;
  if (penMask.tiltXValid()) {
    tiltX = qBound(-60, penInfo.tiltX, 60);
  }
  if (penMask.tiltYValid()) {
    tiltY = qBound(-60, penInfo.tiltY, 60);
  }
  // rotateTiltAngles(tiltX, tiltY, deviceItem.deviceOrientation);

  int rotation = 0;
  if (penMask.rotationValid()) {
    rotation =
        360 - penInfo.rotation;  // Flip direction and convert to signed int
    if (rotation > 180) {
      rotation -= 360;
    }
  }

  return QTabletEvent(
      eventType,             // type
      localPosF,             // pos
      globalPosF,            // globalPos
      QTabletEvent::Stylus,  // device
      pointerType,           // pointerType
      penMask.pressureValid() ? static_cast<qreal>(penInfo.pressure) / 1024
                              : 0,             // pressure
      tiltX,                                   // xTilt
      tiltY,                                   // yTilt
      0,                                       // tangentialPressure
      rotation,                                // rotation
      0,                                       // z
      QApplication::queryKeyboardModifiers(),  // keyState
      reinterpret_cast<qint64>(penInfo.pointerInfo.sourceDevice),  // uniqueID
      mouseButton,                                                 // button
      mouseButtons                                                 // buttons
      );
}

bool sendProximityTabletEvent(const QEvent::Type eventType,
                              const POINTER_PEN_INFO &penInfo) {
#ifdef KRITA
  KIS_SAFE_ASSERT_RECOVER_RETURN_VALUE(
      eventType == QEvent::TabletEnterProximity ||
          eventType == QEvent::TabletLeaveProximity,
      false);
#else
  if (!(eventType == QEvent::TabletEnterProximity ||
        eventType == QEvent::TabletLeaveProximity)) {
    return false;
  }
#endif
  QTabletEvent ev = makeProximityTabletEvent(eventType, penInfo);
  ev.setAccepted(false);
  ev.setTimestamp(penInfo.pointerInfo.dwTime);
  QCoreApplication::sendEvent(qApp, &ev);
  return ev.isAccepted();
}

void synthesizeMouseEvent(const QTabletEvent &ev,
                          const POINTER_PEN_INFO &penInfo) {
  // Update the cursor position
  BOOL result = SetCursorPos(penInfo.pointerInfo.ptPixelLocationRaw.x,
                             penInfo.pointerInfo.ptPixelLocationRaw.y);
  if (!result) {
#ifdef KRITA
    dbgInput << "SetCursorPos failed, err" << GetLastError();
#endif
    return;
  }
  // Send mousebutton down/up events. Windows stores the button state.
  DWORD inputDataFlags = 0;
  switch (ev.type()) {
  case QEvent::TabletPress:
    switch (ev.button()) {
    case Qt::LeftButton:
      inputDataFlags = MOUSEEVENTF_LEFTDOWN;
      break;
    case Qt::RightButton:
      inputDataFlags = MOUSEEVENTF_RIGHTDOWN;
      break;
    default:
      return;
    }
    break;
  case QEvent::TabletRelease:
    switch (ev.button()) {
    case Qt::LeftButton:
      inputDataFlags = MOUSEEVENTF_LEFTUP;
      break;
    case Qt::RightButton:
      inputDataFlags = MOUSEEVENTF_RIGHTUP;
      break;
    default:
      return;
    }
    break;
  case QEvent::TabletMove:
  default:
    return;
  }
  INPUT inputData      = {};
  inputData.type       = INPUT_MOUSE;
  inputData.mi.dwFlags = inputDataFlags;
  inputData.mi.dwExtraInfo =
      0xFF515700 |
      0x01;  // https://msdn.microsoft.com/en-us/library/windows/desktop/ms703320%28v=vs.85%29.aspx
  UINT result2 = SendInput(1, &inputData, sizeof(inputData));
  if (result2 != 1) {
#ifdef KRITA
    dbgInput << "SendInput failed, err" << GetLastError();
#endif
    return;
  }
}

bool sendPositionalTabletEvent(QWidget *target, const QEvent::Type eventType,
                               const POINTER_PEN_INFO &penInfo,
                               const PointerDeviceItem &device,
                               const PenPointerItem &penPointerItem,
                               const bool shouldSynthesizeMouseEvent) {
#ifdef KRITA
  KIS_SAFE_ASSERT_RECOVER_RETURN_VALUE(eventType == QEvent::TabletMove ||
                                           eventType == QEvent::TabletPress ||
                                           eventType == QEvent::TabletRelease,
                                       false);
#else
  if (!(eventType == QEvent::TabletMove || eventType == QEvent::TabletPress ||
        eventType == QEvent::TabletRelease)) {
    return false;
  }
#endif
  QTabletEvent ev = makePositionalTabletEvent(target, eventType, penInfo,
                                              device, penPointerItem);
  ev.setAccepted(false);
  ev.setTimestamp(penInfo.pointerInfo.dwTime);
  QCoreApplication::sendEvent(target, &ev);
  if (!shouldSynthesizeMouseEvent) {
    // For pen update with multiple updates, only the last update should
    // be used to synthesize a mouse event.
    return false;
  }
  // This is some specialized code to handle synthesizing of mouse events from
  // the pen events. Issues being:
  // 1. We must accept the pointer down/up and the intermediate update events
  //    to indicate that we want all the pen pointer events for painting,
  //    otherwise Windows may do weird stuff and skip passing pointer events.
  // 2. Some Qt and Krita code uses QCursor::pos() which calls GetCursorPos to
  //    get the cursor position. This doesn't work nicely before ver 1709 and
  //    doesn't work at all on ver 1709 if the pen events are handled, so we
  //    need some way to nudge the cursor on the OS level.
  // It appears that using the same way (as in synthesizeMouseEvent) to nudge
  // the cursor does work fine for when painting on canvas (which handles
  // the QTabletEvent), but not for other widgets because it introduces a lag
  // with mouse move events on move start and immediately after mouse down.
  // The resolution is to simulate mouse movement with our own code only for
  // handled pen events, which is what the following code does.
  if (ev.type() == QEvent::TabletMove && ev.buttons() == Qt::NoButton) {
    // Let Windows synthesize mouse hover events
    return false;
  }
  if (ev.type() == QEvent::TabletPress && !ev.isAccepted()) {
    // On pen down event, if the widget doesn't handle the event, let
    // Windows translate the event to touch, mouse or whatever
    return false;
  }
  if (ev.type() != QEvent::TabletPress &&
      !penPointerItem.widgetAcceptsPenEvent) {
    // For other events, if the previous pen down event wasn't handled by
    // the widget, continue to let Windows translate the event
    return false;
  }
  // Otherwise, we synthesize our mouse events
  synthesizeMouseEvent(ev, penInfo);
  return true;  // and tell Windows that we do want the pen events.
}

bool handlePenEnterMsg(const POINTER_PEN_INFO &penInfo) {
  PointerFlagsWrapper pointerFlags = PointerFlagsWrapper::fromPenInfo(penInfo);
  if (!pointerFlags.isPrimary()) {
// Don't handle non-primary pointer messages for now
#ifdef KRITA
    dbgTablet << "Pointer" << penInfo.pointerInfo.pointerId << "of device"
              << penInfo.pointerInfo.sourceDevice << "is not flagged PRIMARY";
#endif
    return false;
  }

  // Update the device scaling factors here
  // It doesn't cost much to recalculate anyway
  // This ensures that the screen resolution changes are reflected
  // WM_POINTERDEVICECHANGE might be useful for this, but its docs are too
  // unclear to use
  registerOrUpdateDevice(penInfo.pointerInfo.sourceDevice);
  // TODO: Need a way to remove from device registration when devices are
  // changed

  // We now only handle one pointer at a time, so just clear the pointer
  // registration
  penPointers.clear();

  int pointerId = penInfo.pointerInfo.pointerId;
  PenPointerItem penPointerItem;
  penPointerItem.hwnd                  = penInfo.pointerInfo.hwndTarget;
  penPointerItem.deviceHandle          = penInfo.pointerInfo.sourceDevice;
  penPointerItem.activeWidget          = nullptr;
  penPointerItem.oneOverDpr            = 1.0;
  penPointerItem.widgetIsCaptured      = false;
  penPointerItem.widgetIsIgnored       = false;
  penPointerItem.widgetAcceptsPenEvent = false;
  // penPointerItem.pointerId = pointerId;

  penPointers.insert(pointerId, penPointerItem);
  // primaryPenPointerId = pointerId;

  // penEnter
  sendProximityTabletEvent(QEvent::TabletEnterProximity, penInfo);

  return false;
}

bool handlePenLeaveMsg(const POINTER_PEN_INFO &penInfo) {
  if (!penPointers.contains(penInfo.pointerInfo.pointerId)) {
#ifdef KRITA
    dbgTablet << "Pointer" << penInfo.pointerInfo.pointerId
              << "wasn't being handled";
#endif
    return false;
  }
  if (!penDevices.contains(penInfo.pointerInfo.sourceDevice)) {
#ifdef KRITA
    dbgTablet << "Device is gone from the registration???";
#endif
    // TODO: re-register device?
    penPointers.remove(penInfo.pointerInfo.pointerId);
    return false;
  }

  // penLeave
  sendProximityTabletEvent(QEvent::TabletLeaveProximity, penInfo);

  penPointers.remove(penInfo.pointerInfo.pointerId);

  return false;
}

bool handleSinglePenUpdate(PenPointerItem &penPointerItem,
                           const POINTER_PEN_INFO &penInfo,
                           const PointerDeviceItem &device,
                           const bool shouldSynthesizeMouseEvent) {
  QWidget *targetWidget;
  if (penPointerItem.isCaptured()) {
    if (penPointerItem.widgetIsIgnored) {
      return false;
    }
    targetWidget = penPointerItem.activeWidget;
    if (!targetWidget) {
      return false;
    }
  } else {
    QWidget *hwndWidget =
        QWidget::find(reinterpret_cast<WId>(penInfo.pointerInfo.hwndTarget));
    if (!hwndWidget) {
#ifdef KRITA
      dbgTablet << "HWND cannot be mapped to QWidget (what?)";
#endif
      return false;
    }
    {
      // Check popup / modal widget
      QWidget *modalWidget = QApplication::activePopupWidget();
      if (!modalWidget) {
        modalWidget = QApplication::activeModalWidget();
      }
      if (modalWidget && modalWidget != hwndWidget &&
          !modalWidget->isAncestorOf(hwndWidget)) {
        return false;
      }
    }
    {
      QWindow *topLevelWindow = hwndWidget->windowHandle();
      if (topLevelWindow) {
        penPointerItem.oneOverDpr = 1.0 / topLevelWindow->devicePixelRatio();
      } else {
        penPointerItem.oneOverDpr = 1.0 / qApp->devicePixelRatio();
      }
    }
    QPoint posInHwndWidget = hwndWidget->mapFromGlobal(
        QPoint(static_cast<int>(penInfo.pointerInfo.ptPixelLocationRaw.x *
                                penPointerItem.oneOverDpr),
               static_cast<int>(penInfo.pointerInfo.ptPixelLocationRaw.y *
                                penPointerItem.oneOverDpr)));
    targetWidget = hwndWidget->childAt(posInHwndWidget);
    if (!targetWidget) {
      // dbgTablet << "No childQWidget at cursor position";
      targetWidget = hwndWidget;
    }
    // penPointerItem.activeWidget = targetWidget;
  }

  bool handled = sendPositionalTabletEvent(targetWidget, QEvent::TabletMove,
                                           penInfo, device, penPointerItem,
                                           shouldSynthesizeMouseEvent);
  return handled;
}

bool handlePenUpdateMsg(const POINTER_PEN_INFO &penInfo) {
  auto currentPointerIt = penPointers.find(penInfo.pointerInfo.pointerId);
  if (currentPointerIt == penPointers.end()) {
    // dbgTablet << "Pointer" << penInfo.pointerInfo.pointerId << "wasn't being
    // handled";
    return false;
  }

  const auto devIt = penDevices.find(penInfo.pointerInfo.sourceDevice);
  if (devIt == penDevices.end()) {
#ifdef KRITA
    dbgTablet << "Device not registered???";
#endif
    return false;
  }

  // UINT32 entriesCount = 0;
  // if (!api.GetPointerPenInfoHistory(penInfo.pointerInfo.pointerId,
  // &entriesCount, nullptr)) {
  //     dbgTablet << "GetPointerPenInfoHistory (getting count) failed";
  //     return false;
  // }
  UINT32 entriesCount = penInfo.pointerInfo.historyCount;
  // dbgTablet << "entriesCount:" << entriesCount;
  bool handled = false;
  if (entriesCount != 1) {
    QVector<POINTER_PEN_INFO> penInfoArray(entriesCount);
    if (!api.GetPointerPenInfoHistory(penInfo.pointerInfo.pointerId,
                                      &entriesCount, penInfoArray.data())) {
#ifdef KRITA
      dbgTablet << "GetPointerPenInfoHistory failed";
#endif
      return false;
    }
    bool handled = false;
    // The returned array is in reverse chronological order
    const auto rbegin = penInfoArray.rbegin();
    const auto rend   = penInfoArray.rend();
    const auto rlast =
        rend - 1;  // Only synthesize mouse event for the last one
    for (auto it = rbegin; it != rend; ++it) {
      handled |= handleSinglePenUpdate(
          *currentPointerIt, *it, *devIt,
          it == rlast);  // Bitwise OR doesn't short circuit
    }
  } else {
    handled = handleSinglePenUpdate(*currentPointerIt, penInfo, *devIt, true);
  }
  return handled;
}

bool handlePenDownMsg(const POINTER_PEN_INFO &penInfo) {
  // PointerFlagsWrapper pointerFlags =
  // PointerFlagsWrapper::fromPenInfo(penInfo);
  // if (!pointerFlags.isPrimary()) {
  //     // Don't handle non-primary pointer messages for now
  //     return false;
  // }
  auto currentPointerIt = penPointers.find(penInfo.pointerInfo.pointerId);
  if (currentPointerIt == penPointers.end()) {
#ifdef KRITA
    dbgTablet << "Pointer" << penInfo.pointerInfo.pointerId
              << "wasn't being handled";
#endif
    return false;
  }
  currentPointerIt->hwnd =
      penInfo.pointerInfo
          .hwndTarget;  // They *should* be the same, but just in case
  QWidget *hwndWidget =
      QWidget::find(reinterpret_cast<WId>(penInfo.pointerInfo.hwndTarget));
  if (!hwndWidget) {
#ifdef KRITA
    dbgTablet << "HWND cannot be mapped to QWidget (what?)";
#endif
    return false;
  }
  {
    QWindow *topLevelWindow = hwndWidget->windowHandle();
    if (topLevelWindow) {
      currentPointerIt->oneOverDpr = 1.0 / topLevelWindow->devicePixelRatio();
    } else {
      currentPointerIt->oneOverDpr = 1.0 / qApp->devicePixelRatio();
    }
  }
  QPoint posInHwndWidget = hwndWidget->mapFromGlobal(
      QPoint(static_cast<int>(penInfo.pointerInfo.ptPixelLocationRaw.x *
                              currentPointerIt->oneOverDpr),
             static_cast<int>(penInfo.pointerInfo.ptPixelLocationRaw.y *
                              currentPointerIt->oneOverDpr)));
  QWidget *targetWidget = hwndWidget->childAt(posInHwndWidget);
  if (!targetWidget) {
#ifdef KRITA
    dbgTablet << "No childQWidget at cursor position";
#endif
    targetWidget = hwndWidget;
  }

  currentPointerIt->activeWidget     = targetWidget;
  currentPointerIt->widgetIsCaptured = true;
  // dbgTablet << "QWidget" << targetWidget->windowTitle() << "is capturing
  // pointer" << penInfo.pointerInfo.pointerId;
  {
    // Check popup / modal widget
    QWidget *modalWidget = QApplication::activePopupWidget();
    if (!modalWidget) {
      modalWidget = QApplication::activeModalWidget();
    }
    if (modalWidget && modalWidget != hwndWidget &&
        !modalWidget->isAncestorOf(hwndWidget)) {
      currentPointerIt->widgetIsIgnored = true;
#ifdef KRITA
      dbgTablet << "Pointer" << penInfo.pointerInfo.pointerId
                << "is being captured but will be ignored";
#endif
      return false;
    }
  }

  // penDown
  const auto devIt = penDevices.find(penInfo.pointerInfo.sourceDevice);
  if (devIt == penDevices.end()) {
#ifdef KRITA
    dbgTablet << "Device not registered???";
#endif
    return false;
  }

  bool handled =
      sendPositionalTabletEvent(targetWidget, QEvent::TabletPress, penInfo,
                                *devIt, *currentPointerIt, true);
  currentPointerIt->widgetAcceptsPenEvent = handled;
  if (!handled) {
    // dbgTablet << "QWidget did not handle tablet down event";
  }
  return handled;
}

bool handlePenUpMsg(const POINTER_PEN_INFO &penInfo) {
  auto currentPointerIt = penPointers.find(penInfo.pointerInfo.pointerId);
  if (currentPointerIt == penPointers.end()) {
#ifdef KRITA
    dbgTablet << "Pointer" << penInfo.pointerInfo.pointerId
              << "wasn't being handled";
#endif
    return false;
  }
  PenPointerItem &penPointerItem = *currentPointerIt;

  if (!penPointerItem.isCaptured()) {
#ifdef KRITA
    dbgTablet << "Pointer wasn't captured";
#endif
    return false;
  }
  if (penPointerItem.widgetIsIgnored) {
    penPointerItem.widgetIsCaptured = false;
    penPointerItem.widgetIsIgnored  = false;
    return false;
  }

  // penUp
  QWidget *targetWidget = penPointerItem.activeWidget;
  if (!targetWidget) {
#ifdef KRITA
    dbgTablet << "Previously captured target has been deleted";
#endif
    penPointerItem.widgetIsCaptured = false;
    return false;
  }

  const auto devIt = penDevices.find(penInfo.pointerInfo.sourceDevice);
  if (devIt == penDevices.end()) {
#ifdef KRITA
    dbgTablet << "Device not registered???";
#endif
    return false;
  }

  bool handled =
      sendPositionalTabletEvent(targetWidget, QEvent::TabletRelease, penInfo,
                                *devIt, penPointerItem, true);

  // dbgTablet << "QWidget" << currentPointerIt->activeWidget->windowTitle() <<
  // "is releasing capture to pointer" << penInfo.pointerInfo.pointerId;
  penPointerItem.widgetIsCaptured      = false;
  penPointerItem.widgetAcceptsPenEvent = false;
  return handled;
}

bool handlePointerMsg(const MSG &msg) {
  if (!api.isLoaded()) {
    qWarning() << "Windows 8 Pointer Input API functions not loaded";
    return false;
  }

  int pointerId = GET_POINTERID_WPARAM(msg.wParam);
  POINTER_INPUT_TYPE pointerType;
  if (!api.GetPointerType(pointerId, &pointerType)) {
#ifdef KRITA
    dbgTablet << "GetPointerType failed";
#endif
    return false;
  }
  if (pointerType != PT_PEN) {
    // dbgTablet << "pointerType" << pointerType << "is not PT_PEN";
    return false;
  }

  POINTER_PEN_INFO penInfo;
  if (!api.GetPointerPenInfo(pointerId, &penInfo)) {
#ifdef KRITA
    dbgTablet << "GetPointerPenInfo failed";
#endif
    return false;
  }

  switch (msg.message) {
  case WM_POINTERDOWN:
    // dbgTablet << "WM_POINTERDOWN";
    break;
  case WM_POINTERUP:
    // dbgTablet << "WM_POINTERUP";
    break;
  case WM_POINTERENTER:
    // dbgTablet << "WM_POINTERENTER";
    break;
  case WM_POINTERLEAVE:
    // dbgTablet << "WM_POINTERLEAVE";
    break;
  case WM_POINTERUPDATE:
    // dbgTablet << "WM_POINTERUPDATE";
    break;
  case WM_POINTERCAPTURECHANGED:
    // dbgTablet << "WM_POINTERCAPTURECHANGED";
    break;
  default:
#ifdef KRITA
    dbgTablet << "I missed this message: " << msg.message;
#endif
    break;
  }
  // dbgTablet << "  hwnd:        " << penInfo.pointerInfo.hwndTarget;
  // dbgTablet << "  msg hwnd:    " << msg.hwnd;
  // dbgTablet << "  pointerId:   " << pointerId;
  // dbgTablet << "  sourceDevice:" << penInfo.pointerInfo.sourceDevice;
  // dbgTablet << "  pointerFlags:" << penInfo.pointerInfo.pointerFlags;
  // dbgTablet << "  btnChgType:  " << penInfo.pointerInfo.ButtonChangeType;
  // dbgTablet << "  penFlags:    " << penInfo.penFlags;
  // dbgTablet << "  penMask:     " << penInfo.penMask;
  // dbgTablet << "  pressure:    " << penInfo.pressure;
  // dbgTablet << "  rotation:    " << penInfo.rotation;
  // dbgTablet << "  tiltX:       " << penInfo.tiltX;
  // dbgTablet << "  tiltY:       " << penInfo.tiltY;
  // dbgTablet << "  ptPixelLocationRaw:   " <<
  // penInfo.pointerInfo.ptPixelLocationRaw;
  // dbgTablet << "  ptHimetricLocationRaw:" <<
  // penInfo.pointerInfo.ptHimetricLocationRaw;
  // RECT pointerDeviceRect, displayRect;
  // if (!api.GetPointerDeviceRects(penInfo.pointerInfo.sourceDevice,
  // &pointerDeviceRect, &displayRect)) {
  //     dbgTablet << "GetPointerDeviceRects failed";
  //     return false;
  // }
  // dbgTablet << "  pointerDeviceRect:" << pointerDeviceRect;
  // dbgTablet << "  displayRect:" << displayRect;
  // dbgTablet << "  scaled X:" <<
  // static_cast<qreal>(penInfo.pointerInfo.ptHimetricLocationRaw.x) /
  // (pointerDeviceRect.right - pointerDeviceRect.left) * (displayRect.right -
  // displayRect.left);
  // dbgTablet << "  scaled Y:" <<
  // static_cast<qreal>(penInfo.pointerInfo.ptHimetricLocationRaw.y) /
  // (pointerDeviceRect.bottom - pointerDeviceRect.top) * (displayRect.bottom -
  // displayRect.top);

  switch (msg.message) {
  case WM_POINTERDOWN:
    return handlePenDownMsg(penInfo);
  case WM_POINTERUP:
    return handlePenUpMsg(penInfo);
  case WM_POINTERENTER:
    return handlePenEnterMsg(penInfo);
  case WM_POINTERLEAVE:
    return handlePenLeaveMsg(penInfo);
  case WM_POINTERUPDATE:
    return handlePenUpdateMsg(penInfo);
  case WM_POINTERCAPTURECHANGED:
// TODO: Should this event be handled?
#ifdef KRITA
    dbgTablet << "FIXME: WM_POINTERCAPTURECHANGED isn't handled";
#endif
    break;
  }

  return false;
}

}  // namespace

#endif  // _WIN32

{'repo_name': 'opentoonz/opentoonz', 'stars': '2801', 'repo_language': 'C++', 'file_name': 'CMakeLists.txt', 'mime_type': 'text/plain', 'hash': -4044862753927245742, 'source_dataset': 'data'}


from base import BaseTest

import re

ecs_version_log = "\"ecs.version\":"
ecs_timestamp_log = "\"@timestamp\":"
ecs_message_log = "\"message\":"
ecs_log_level_log = "\"log.level\":"

class TestLogging(BaseTest):

    def run_beat_with_args(self, msg, logging_args=[], extra_args=[]):
        self.render_config_template(
            console={"pretty": "false"}
        )
        proc = self.start_beat(logging_args=logging_args, extra_args=extra_args)
        self.wait_until(lambda: self.log_contains(msg),
                        max_timeout=2)
        proc.check_kill_and_wait()

    def assert_contains_ecs_log(self, logfile=None):
        assert self.log_contains(ecs_version_log, logfile=logfile)
        assert self.log_contains(ecs_timestamp_log, logfile=logfile)
        assert self.log_contains(ecs_message_log, logfile=logfile)
        assert self.log_contains(ecs_log_level_log, logfile=logfile)

    def assert_not_contains_ecs_log(self, logfile=None):
        assert not self.log_contains(ecs_version_log, logfile=logfile)
        assert not self.log_contains(ecs_timestamp_log, logfile=logfile)
        assert not self.log_contains(ecs_log_level_log, logfile=logfile)

    def test_console_default(self):
        """
        logs to console with default format
        """
        self.run_beat_with_args("mockbeat start running", logging_args=["-e"])
        self.assert_not_contains_ecs_log()

    def test_console_ecs(self):
        """
        logs to console with ECS format
        """
        self.run_beat_with_args("mockbeat start running",
                                logging_args=["-e"],
                                extra_args=["-E", "logging.json=true",
                                            "-E", "logging.ecs=true"])
        self.assert_contains_ecs_log()

    def test_file_default(self):
        """
        logs to file with default format
        """
        self.run_beat_with_args("Mockbeat is alive!",
                                logging_args=[],
                                extra_args=["-E", "logging.json=true",
                                            "-E", "logging.ecs=false"])
        self.assert_not_contains_ecs_log(logfile="logs/mockbeat")

    def test_file_ecs(self):
        """
        logs to file with ECS format
        """
        self.run_beat_with_args("Mockbeat is alive!",
                                extra_args=["-E", "logging.json=true",
                                            "-E", "logging.ecs=true"])
        self.assert_contains_ecs_log(logfile="logs/mockbeat")

{'repo_name': 'elastic/beats', 'stars': '9014', 'repo_language': 'Go', 'file_name': 'generate.go', 'mime_type': 'text/plain', 'hash': -3235833556030280984, 'source_dataset': 'data'}


import GRT
import sys
import argparse

def main():
    '''
     GRT Softmax Example
     This examples demonstrates how to initialize, train, and use the Softmax algorithm for classification.

     The Softmax classifier is a simple but effective classifier based on logisitic regression that works well on problems that are linearly separable.

     In this example we create an instance of an Softmax algorithm and then train the algorithm using some pre-recorded training data.
     The trained Softmax classification model is then used to predict the class label of some test data.

     This example shows you how to:
     - Create an initialize the Softmax algorithm
     - Load some ClassificationData from a file and partition the training data into a training dataset and a test dataset
     - Train the Softmax algorithm using the training dataset
     - Test the Softmax algorithm using the test dataset
     - Manually compute the accuracy of the classifier

    You should run this example with one argument pointing to the data you want to load. A good dataset to run this example is acc-orientation.grt, which can be found in the GRT data folder.
    '''

    # Parse the data filename from the argument list
    parser = argparse.ArgumentParser(description='Process some data.')
    parser.add_argument('filename', help='A data file')
    args = parser.parse_args()

    filename = args.filename

    # Create a new Softmax instance
    softmax = GRT.Softmax()

    # Load some training data to train the classifier
    trainingData = GRT.ClassificationData()

    if not trainingData.load( filename ):
        print("Failed to load training data: %s" % filename)
        sys.exit(1)

    # Use 20% of the training dataset to create a test dataset
    testData = trainingData.split( 80 )

    # Train the classifier
    if not softmax.train( trainingData ):
        print("Failed to train classifier!")
        sys.exit(1)

    # Save the model to a file
    if not softmax.save("SoftmaxModel.grt"):
        print("Failed to save the classifier model!")
        sys.exit(1)

    # Load the model from a file
    if not softmax.load("SoftmaxModel.grt"):
        print("Failed to load the classifier model!")
        sys.exit(1)

    # Use the test dataset to test the BAG model
    accuracy = 0.0
    for i in range(testData.getNumSamples()):
        # Get the i'th test sample
        classLabel = testData.get(i).getClassLabel()
        inputVector = testData.get(i).getSample()

        # Perform a prediction using the classifier
        if not softmax.predict( inputVector ):
            print("Failed to perform prediction for test sample: %d" % i)
            sys.exit(1)

        # Get the predicted class label
        predictedClassLabel = softmax.getPredictedClassLabel()
        classLikelihoods = softmax.getClassLikelihoods()
        classDistances = softmax.getClassDistances()

        # Update the accuracy
        if classLabel == predictedClassLabel:
            accuracy += 1

        # Print out the results
        print("TestSample: %d  ClassLabel: %d PredictedClassLabel: %d" % (i, classLabel, predictedClassLabel))

        print(" ClassLikelihoods: " + str(classLikelihoods))
        print(" ClassDistances: " + str(classDistances))

    print("Test Accuracy: %.3f%%" % (accuracy/float(testData.getNumSamples())*100.0))

    return 0

if __name__ == '__main__':
    sys.exit(main())

{'repo_name': 'nickgillian/grt', 'stars': '702', 'repo_language': 'C++', 'file_name': 'gmock-port.h', 'mime_type': 'text/x-c', 'hash': -3500240993127485448, 'source_dataset': 'data'}


// This file is Part of CalDavSynchronizer (http://outlookcaldavsynchronizer.sourceforge.net/)
// Copyright (c) 2015 Gerhard Zehetbauer
// Copyright (c) 2015 Alexander Nimmervoll
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero 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 Affero General Public License for more details.
//
// You should have received a copy of the GNU Affero General Public License
// along with this program.  If not, see <http://www.gnu.org/licenses/>.
using System;
using System.Linq;
using System.Threading.Tasks;
using CalDavSynchronizer.Contracts;
using CalDavSynchronizer.Implementation;
using CalDavSynchronizer.Implementation.Events;
using CalDavSynchronizer.IntegrationTests.Infrastructure;
using CalDavSynchronizer.IntegrationTests.TestBase;
using DDay.iCal;
using GenSync.Logging;
using NUnit.Framework;

namespace CalDavSynchronizer.IntegrationTests
{

  class TaskSynchronizerFixture
  {
    private TestComponentContainer _testComponentContainer;

    [OneTimeSetUp]
    public void OneTimeSetup()
    {
      _testComponentContainer = new TestComponentContainer();
    }

    [Test]
    [TestCase(true)]
    [TestCase(false)]
    [Apartment(System.Threading.ApartmentState.STA)]
    public async Task CreateOutlookEntity_ExceptionOccurs_DoesNotLeaveEmptyEntityInRepository(bool saveAndReload)
    {
      var options = _testComponentContainer.TestOptionsFactory.CreateSogoTasks();
      var synchronizer = await CreateSynchronizer(options);
      await synchronizer.ClearEventRepositoriesAndCache();

      bool exceptionCatched = false;

      var exception = new Exception("bla");
      try
      {
        await synchronizer.Components.OutlookRepository.Create(
          w =>
          {
            if(saveAndReload)
              w.SaveAndReload();
            throw exception;
          },
          0);
      }
      catch (Exception x)
      {
        if(ReferenceEquals(x, exception))
          exceptionCatched = true;
      }

      Assert.That(exceptionCatched, Is.EqualTo(true));

      Assert.That(
        (await synchronizer.Outlook.GetAllEntities()).Count(),
        Is.EqualTo(0));
    }

    private async Task<TaskTestSynchronizer> CreateSynchronizer(Options options)
    {
      var synchronizer = new TaskTestSynchronizer(options, _testComponentContainer);
      await synchronizer.Initialize();
      return synchronizer;
    }
  }
}

{'repo_name': 'aluxnimm/outlookcaldavsynchronizer', 'stars': '490', 'repo_language': 'C#', 'file_name': 'ConflictInitialSyncStateCreationStrategyAWins.cs', 'mime_type': 'text/plain', 'hash': -7155065369822561000, 'source_dataset': 'data'}


package com.airbnb.lottie.parser;

import android.graphics.Rect;

import com.airbnb.lottie.LottieComposition;
import com.airbnb.lottie.LottieImageAsset;
import com.airbnb.lottie.model.Font;
import com.airbnb.lottie.model.FontCharacter;
import com.airbnb.lottie.model.Marker;
import com.airbnb.lottie.model.layer.Layer;
import com.airbnb.lottie.parser.moshi.JsonReader;
import com.airbnb.lottie.utils.Logger;
import com.airbnb.lottie.utils.Utils;

import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import androidx.collection.LongSparseArray;
import androidx.collection.SparseArrayCompat;

public class LottieCompositionParser {
  static JsonReader.Options NAMES = JsonReader.Options.of(
      "w",
      "h",
      "ip",
      "op",
      "fr",
      "v",
      "layers",
      "assets",
      "fonts",
      "chars",
      "markers");

  public static LottieComposition parse(JsonReader reader) throws IOException {
    float scale = Utils.dpScale();
    float startFrame = 0f;
    float endFrame = 0f;
    float frameRate = 0f;
    final LongSparseArray<Layer> layerMap = new LongSparseArray<>();
    final List<Layer> layers = new ArrayList<>();
    int width = 0;
    int height = 0;
    Map<String, List<Layer>> precomps = new HashMap<>();
    Map<String, LottieImageAsset> images = new HashMap<>();
    Map<String, Font> fonts = new HashMap<>();
    List<Marker> markers = new ArrayList<>();
    SparseArrayCompat<FontCharacter> characters = new SparseArrayCompat<>();

    LottieComposition composition = new LottieComposition();
    reader.beginObject();
    while (reader.hasNext()) {
      switch (reader.selectName(NAMES)) {
        case 0:
          width = reader.nextInt();
          break;
        case 1:
          height = reader.nextInt();
          break;
        case 2:
          startFrame = (float) reader.nextDouble();
          break;
        case 3:
          endFrame = (float) reader.nextDouble() - 0.01f;
          break;
        case 4:
          frameRate = (float) reader.nextDouble();
          break;
        case 5:
          String version = reader.nextString();
          String[] versions = version.split("\\.");
          int majorVersion = Integer.parseInt(versions[0]);
          int minorVersion = Integer.parseInt(versions[1]);
          int patchVersion = Integer.parseInt(versions[2]);
          if (!Utils.isAtLeastVersion(majorVersion, minorVersion, patchVersion,
              4, 4, 0)) {
            composition.addWarning("Lottie only supports bodymovin >= 4.4.0");
          }
          break;
        case 6:
          parseLayers(reader, composition, layers, layerMap);
        default:
          reader.skipValue();

      }
    }
    int scaledWidth = (int) (width * scale);
    int scaledHeight = (int) (height * scale);
    Rect bounds = new Rect(0, 0, scaledWidth, scaledHeight);

    composition.init(bounds, startFrame, endFrame, frameRate, layers, layerMap, precomps,
        images, characters, fonts, markers);

    return composition;
  }

  private static void parseLayers(JsonReader reader, LottieComposition composition,
                                  List<Layer> layers, LongSparseArray<Layer> layerMap) throws IOException {
    int imageCount = 0;
    reader.beginArray();
    while (reader.hasNext()) {
      Layer layer = LayerParser.parse(reader, composition);
      if (layer.getLayerType() == Layer.LayerType.IMAGE) {
        imageCount++;
      }
      layers.add(layer);
      layerMap.put(layer.getId(), layer);

      if (imageCount > 4) {
        Logger.warning("You have " + imageCount + " images. Lottie should primarily be " +
            "used with shapes. If you are using Adobe Illustrator, convert the Illustrator layers" +
            " to shape layers.");
      }
    }
    reader.endArray();
  }
}

{'repo_name': 'airbnb/lottie-android', 'stars': '29246', 'repo_language': 'Java', 'file_name': 'AndroidManifest.xml', 'mime_type': 'text/plain', 'hash': -6024238337868485816, 'source_dataset': 'data'}


{#
/**
 * Copyright (C) 2020 Xibo Signage Ltd
 *
 * Xibo - Digital Signage - http://www.xibo.org.uk
 *
 * This file is part of Xibo.
 *
 * Xibo is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Affero General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * any later version.
 *
 * Xibo 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 Affero General Public License for more details.
 *
 * You should have received a copy of the GNU Affero General Public License
 * along with Xibo.  If not, see <http://www.gnu.org/licenses/>.
 */
#}

{% extends "form-base.twig" %}
{% import "forms.twig" as forms %}

{% block formTitle %}
    {% trans "Add Application" %}
{% endblock %}

{% block formButtons %}
    {% trans "Cancel" %}, XiboDialogClose()
    {% trans "Help" %}, XiboHelpRender("{{ help }}")
    {% trans "Save" %}, $("#applicationFormSubmit").submit()
{% endblock %}

{% block formHtml %}

            <form id="applicationFormSubmit" class="XiboForm form-horizontal" method="post" action="{{ url_for("application.add") }}"
                  data-next-form-url="{{ url_for("application.edit.form", {id:':id'}) }}" data-next-form-id-property="key">
                {% set title %}{% trans "Application Name" %}{% endset %}
                {{ forms.input("name", title) }}
            </form>

{% endblock %}

{'repo_name': 'xibosignage/xibo-cms', 'stars': '225', 'repo_language': 'PHP', 'file_name': 'layout-form-retire.twig', 'mime_type': 'text/plain', 'hash': -7334530305926131714, 'source_dataset': 'data'}


// DejaLu
// Copyright (c) 2015 Hoa V. DINH. All rights reserved.

#import "DJLConversationListPlaceholderView.h"

#import "NSImage+DJLColored.h"
#import "DJLColoredProgressIndicator.h"
#import "DJLDarkMode.h"
#import "FBKVOController.h"

@implementation DJLConversationListPlaceholderView {
    NSImage * _noMessagesImage;
    NSImage * _notLoadedImage;
    NSImage * _loadingImage;
    NSImage * _searchingImage;
    NSImage * _inboxZeroImage;
    DJLColoredProgressIndicator * _progressIndicator;
    FBKVOController * _kvoController;
}

@synthesize kind = _kind;

- (id) initWithFrame:(NSRect)frameRect
{
    self = [super initWithFrame:frameRect];
    _kind = DJLConversationListPlaceholderKindNone;
    CGFloat x = (int) (([self bounds].size.width - 32) / 2);
    _progressIndicator = [[DJLColoredProgressIndicator alloc] initWithFrame:NSMakeRect(x, [self bounds].size.height - 280, 32, 32)];
    [_progressIndicator setAutoresizingMask:NSViewMinXMargin | NSViewMaxXMargin | NSViewMinYMargin];
    [_progressIndicator setColor:[NSColor colorWithCalibratedWhite:0.5 alpha:1.0]];
    [_progressIndicator setHidden:YES];
    [self addSubview:_progressIndicator];
    return self;
}

- (void)viewDidMoveToSuperview
{
    [super viewDidMoveToSuperview];
    if ([self superview] == nil) {
        _kvoController = nil;
    } else {
        _kvoController = [FBKVOController controllerWithObserver:self];
        __weak typeof(self) weakSelf = self;
        [_kvoController observe:weakSelf keyPath:@"effectiveAppearance" options:0 block:^(id observer, id object, NSDictionary * change) {
            _noMessagesImage = nil;
            _notLoadedImage = nil;
            _loadingImage = nil;
            _searchingImage = nil;
            _inboxZeroImage = nil;
            [weakSelf setNeedsDisplay:YES];
        }];
    }
}

- (void)drawRect:(NSRect)dirtyRect {
    [super drawRect:dirtyRect];

    if (_kind == DJLConversationListPlaceholderKindNone) {
        return;
    }

    NSColor * color;
    NSColor * textColor;
    if ([DJLDarkMode isDarkModeForView:self]) {
        color = [NSColor colorWithCalibratedWhite:1.0 alpha:0.3];
        textColor = [NSColor colorWithCalibratedWhite:1.0 alpha:0.4];
    } else {
        color = [NSColor colorWithCalibratedWhite:0.0 alpha:0.3];
        textColor = [NSColor colorWithCalibratedWhite:0.0 alpha:0.4];
    }

    //int iconSize = 0;
    int top = 0;
    int textTop = 0;
    NSImage * image = nil;
    NSString * text = nil;
    switch (_kind) {
        case DJLConversationListPlaceholderKindInboxZero:
            //iconSize = 200;
            if (_inboxZeroImage == nil) {
                NSImage * originImage = [NSImage imageNamed:@"DejaLu_InboxZero_128"];
                //originImage = [originImage copy];
                //[originImage setSize:NSMakeSize(iconSize, iconSize)];
                NSImage * img = [originImage djl_imageWithColor:color];
                _inboxZeroImage = img;
            }
            top = 180;
            textTop = 370;
            text = @"No messages";
            image = _inboxZeroImage;
            break;
        case DJLConversationListPlaceholderKindEmpty:
            if (_noMessagesImage == nil) {
                NSImage * originImage = [NSImage imageNamed:@"DejaLu_Empty_128"];
                NSImage * img = [originImage djl_imageWithColor:color];
                _noMessagesImage = img;
            }
            top = 180;
            textTop = 400;
            text = @"No messages";
            image = _noMessagesImage;
            break;
        case DJLConversationListPlaceholderKindLoading:
            if (_loadingImage == nil) {
                NSImage * originImage = [NSImage imageNamed:@"DejaLu_GettingEmail_128"];
                NSImage * img = [originImage djl_imageWithColor:color];
                _loadingImage = img;
            }
            top = 180;
            textTop = 400;
            text = @"";
            image = _loadingImage;
            break;
        case DJLConversationListPlaceholderKindNotLoaded:
            if (_notLoadedImage == nil) {
                NSImage * originImage = [NSImage imageNamed:@"DejaLu_NetworkErrorOff_128"];
                NSImage * img = [originImage djl_imageWithColor:color];
                _notLoadedImage = img;
            }
            top = 180;
            textTop = 400;
            text = @"Not loaded";
            image = _notLoadedImage;
            break;
        case DJLConversationListPlaceholderKindSearching:
            if (_searchingImage == nil) {
                NSImage * originImage = [NSImage imageNamed:@"DejaLu_Search_128"];
                NSImage * img = [originImage djl_imageWithColor:color];
                _searchingImage = img;
            }
            top = 180;
            textTop = 400;
            text = @"Searching";
            image = _searchingImage;
            break;
        case DJLConversationListPlaceholderKindNoAccounts:
            if (_noMessagesImage == nil) {
                NSImage * originImage = [NSImage imageNamed:@"DejaLu_Empty_128"];
                NSImage * img = [originImage djl_imageWithColor:color];
                _noMessagesImage = img;
            }
            top = 180;
            textTop = 400;
            text = @"No accounts";
            image = _noMessagesImage;
            break;
        default:
            // Do nothing.
            break;
    }

    NSRect bounds = [self bounds];
    NSSize imageSize = [image size];
    NSRect rect = NSMakeRect((bounds.size.width - imageSize.width) / 2, bounds.size.height - top, imageSize.width, imageSize.height);
    rect = NSIntegralRect(rect);
    [image drawInRect:rect];

    NSMutableParagraphStyle * paragraphStyle = [[NSMutableParagraphStyle alloc] init];
    [paragraphStyle setAlignment:NSTextAlignmentCenter];
    [text drawInRect:NSMakeRect(0, bounds.size.height - textTop, bounds.size.width, 200)
      withAttributes:@{NSFontAttributeName: [NSFont boldSystemFontOfSize:18], NSParagraphStyleAttributeName: paragraphStyle, NSForegroundColorAttributeName: textColor}];
}

- (void) setKind:(DJLConversationListPlaceholderKind)kind
{
    _kind = kind;
    [self setNeedsDisplay:YES];
    if (_kind == DJLConversationListPlaceholderKindSearching) {
        [_progressIndicator setHidden:NO];
        [_progressIndicator startAnimation:nil];
    }
    else {
        [_progressIndicator setHidden:YES];
        [_progressIndicator stopAnimation:nil];
    }
}

@end

{'repo_name': 'dinhvh/dejalu', 'stars': '574', 'repo_language': 'C++', 'file_name': 'MainMenu.xib', 'mime_type': 'text/xml', 'hash': 9208548762700155812, 'source_dataset': 'data'}


var apiwriter = require('apiwriter');

exports.getContext = function() {
    return {
        repositoryId: null,
        repositoryName: null,
        projectId: this.getConfig().getProjectId()
    };
};

var _getProj = function (context) {
    return {
        "id": context.projectId,
        "name": context.projName
    }
}

exports.submitRequests = function()
{
	// Create a repository
    apiwriter.postJson('/git/repositories',
        function(context, result) {
            return { "name": "AnotherRepository", "project": _getProj(context) }
        },
        function(context, result) {
            context.repositoryId = result.responseBody.id;
            context.repositoryName = result.responseBody.name;
        }
    );

	// Get details about the new repository
    apiwriter.getJson('/git/repositories/{repositoryId}');

//    apiwriter.getJson('/git/{projectId}/repositories/{repositoryName}');

	// Get a list of repositories
    apiwriter.getJson('/git/repositories');

    /*apiwriter.getJson('/git/{projectId}/repositories',
        function (context, result) {
            context.projName = result.responseBody.value[0].project.name;
        });*/

	// Update a repository
    apiwriter.patchJson('/git/repositories/{repositoryId}',
        function(context, result) {
            return {"name": "RenamedRepository"}
        }
    );

	// Delete a repository
    apiwriter.deleteJson('/git/repositories/{repositoryId}', null);
}

{'repo_name': 'MicrosoftDocs/azure-devops-docs', 'stars': '330', 'repo_language': 'Shell', 'file_name': 'settings.json', 'mime_type': 'text/plain', 'hash': -340823382444628292, 'source_dataset': 'data'}


package org.bouncycastle.util.io;

import java.io.IOException;
import java.io.OutputStream;

/**
 * An output stream which copies anything written into it to another stream.
 */
public class TeeOutputStream
    extends OutputStream
{
    private OutputStream output1;
    private OutputStream output2;

    /**
     * Base constructor.
     *
     * @param output1 the output stream that is wrapped.
     * @param output2 a secondary stream that anything written to output1 is also written to.
     */
    public TeeOutputStream(OutputStream output1, OutputStream output2)
    {
        this.output1 = output1;
        this.output2 = output2;
    }

    public void write(byte[] buf)
        throws IOException
    {
        this.output1.write(buf);
        this.output2.write(buf);
    }

    public void write(byte[] buf, int off, int len)
        throws IOException
    {
        this.output1.write(buf, off, len);
        this.output2.write(buf, off, len);
    }

    public void write(int b)
        throws IOException
    {
        this.output1.write(b);
        this.output2.write(b);
    }

    public void flush()
        throws IOException
    {
        this.output1.flush();
        this.output2.flush();
    }

    public void close()
        throws IOException
    {
        this.output1.close();
        this.output2.close();
    }
}

{'repo_name': 'bcgit/bc-java', 'stars': '1204', 'repo_language': 'Java', 'file_name': 'ecrypt_HC-128.txt', 'mime_type': 'text/plain', 'hash': -604470052992919617, 'source_dataset': 'data'}


/*******************************************************************************
 * Copyright (c) 2004, 2006 QNX Software Systems and others.
 *
 * This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License 2.0
 * which accompanies this distribution, and is available at
 * https://www.eclipse.org/legal/epl-2.0/
 *
 * SPDX-License-Identifier: EPL-2.0
 *
 * Contributors:
 * QNX Software Systems - Initial API and implementation
 *******************************************************************************/
package org.eclipse.cdt.debug.core.model;

import org.eclipse.debug.core.DebugException;

/**
 * Provides support for enable/disable actions.
 */
public interface IEnableDisableTarget {

	/**
	 * Returns whether this object supports enable/disable operations.
	 *
	 * @return whether this object supports enable/disable operations
	 */
	boolean canEnableDisable();

	/**
	 * Returns whether this object is enabled.
	 *
	 * @return true if this obvject is enabled,
	 * 		   or false otherwise.
	 */
	boolean isEnabled();

	/**
	 * Enables/disables this object
	 *
	 * @param enabled enablement flag value
	 * @throws DebugException
	 */
	void setEnabled(boolean enabled) throws DebugException;
}

{'repo_name': 'eclipse-cdt/cdt', 'stars': '129', 'repo_language': 'Java', 'file_name': 'ReferencedProjectsLanguageSettingsProvider.java', 'mime_type': 'text/x-java', 'hash': -8070279288769927705, 'source_dataset': 'data'}


Създаване, промяна и бързо превключване между групи от раздели

Description of the extension.

Настройки

Settings context button title

Управление на групите

Manage groups

Пиктограмата на раздела е пиктограма на групата

Set tab icon as group icon

Преместване в друга група

Move tab to group title

Разделът „$tabtitle$“ е преместен в група „$grouptitle$“.

Отваряне на раздела.

Tab moved popup title

Внимание!

Warning!

Успех!

Success!

Добре

OK button

Запазване

Save

Изтриване

Delete

Отказ

Cancel

Търсене

Search placeholder

Правилото „$regexp$“ е грешно и ще бъде пропуснато.

Invalid rule description

Решетка

Grid display

Свободна подредба (в бъдещо издание)

Free arrange

Затваряне на менюто при смяна на група

Close popup after changing group

Известие при автоматично преместване на раздел

Show notification when tab is moved to another group

Отваряне на „Управление на групите“ в раздел

Open "Manage Groups" in new tab

Потвърждаване при изтриване на група

Show confirm dialog before group delete

Резервни копия

Backup your Simple Tab Groups

Създайте резервни копия на групите от раздели, така че да ги възстановите при нужда.

Export your tab groups into a backup file for safe-keeping, so that you can restore them at a later time if necessary.

Създаване

Create backup

Миниатюри на разделите (увеличава размера на резервното копие)

Include tab thumbnails in backup (makes backup file size bigger)

Възстановяване на групи от резервно копие

Restore Simple Tab Groups

Внесете резервно копие на групите, които да бъдат възстановени.

Load a backup file containing the tab groups you want to restore.

Възстановяване

Restore backup

Възстановяване на „Tab Groups“ от Quicksaver

Restore Quicksaver's "Tab Groups"

Внесете резервно копие от старата добавка „Tab Groups“.

Load a backup file old "Tab Groups" addon.

Отваряне на групата след смяна

Open group after changing to it

Група $id$

group id

Няма резултати за „$search$“

No results found

Подреждане [А-Я]

Sort groups [A-Z]

Подреждане [Я-А]

Sort groups [Z-A]

Общи

General

Настройки на групата

Group settings

Изтриване на групата

Delete group

Изтриване на групата?

Delete group?

Желаете ли групата „$name$“ да бъде изтрита?<br>При изтриване на група разделите и прозорците в нея биват затваряни.

Delete group?

$count$ раздела

Group tabs count

$active$/$count$ отворени раздела

Group tabs count active

Изтриване на раздел

Delete tab

Нов раздел

Open new tab

Нова група

Create new group

Назад

Go back

Списък с групи

Go back to groups

Заглавие

Title

Цвят на пиктограмата

Icon color

Избиране на пиктограма

Load icon

Извинете, не може да избирате пиктограма от това меню, но може в прозореца за управление на групите.  Желаете ли прозореца за управление на групите да бъде отворен?

Sorry, you can't load custom icon in this popup, but you can load custom group icon in "Manage groups".
Open "Manage groups"?

Произволен цвят

Set random color

Преместване на разделите от групата в изолатори

Catch and move tabs with containers to this group

Регулярен израз за улавяне на раздели

Regular expressions for catch tabs

Регулярни изрази

Regular expressions

Въведете регулярни изрази за адреси от мрежата. При съвпадение разделът автоматично ще бъде премесен в тази група.
Едно правило на ред, но може да има неограничен брой правила.
Примери:
github\.com/drive4ik/simple-tab-groups - прехваща страниците от хранилището на добавката
bugzilla\.mozilla\.org - прехваща страници от дефектите на Firefox
(facebook|twitter|youtube)\.com - прехваща страници от социалните мрежи

Regular exceptions helper

Клавишни комбинации

Hotkeys

Тук се добавят клавишни комбинации.
Ограничения:
1. Тези клавишни комбинации ще работят само в страници от интернет (http:, https:), а не в служебните (about:) страници на четеца, защото ППИ на WebExtensions не го позволява.
2. Някои комбинации няма да работят с всички клавиатурни подредби. Например, комбинацията Ctrl + ~, създадена с актива английска подредба няма да работи ако в момента е активна българската, защото в българската подредба този клавиш има друг код. За да заобиколите този недостатък просто създайте същата комбинация докато е активна българска клавиатурна подредба: Ctrl + Ю.

Hotkeys description

Нова комбинация

Add hotkey

Изтриване на комбинацията

Delete hotkey

Натиснете комбинация

Press key here

Избиране

Select action

Избор на група

Select group

Отваряне на следващата група

Load next group

Отваряне на предишната група

Load previous group

Отваряне на следващата неотваряна група

Load next unloaded group

Отваряне на предишната неотваряна група

Load previous unloaded group

Отваряне на следващата група от историята

Load next group from history

Отваряне на предишната група от историята

Load previous group from history

Отваряне на първата група

Load first group

Отваряне на последната група

Load last group

Отваряне на определена група

Load custom group

Нова група

Add new group

Изтриване на текущата група

Delete current group

Отваряне на управлението на групи

Open manage groups

Преместване на раздела в определена група

Move active tab to custom group

Освобождаване на памет от разделите в групата

Hotkey action Discard group

Освобождаване на памет от разделите в другите групи

Hotkey action Discard other groups

Презареждане на разделите в групата

Reload all tabs in current group

Какво се случи?
Изпратете съобщение на разработчика на електронния адрес за поддръжка като прикачите журнала. В настройките на добавката най-долу има отметка.

Whats wrong...
Please contact with developer by support email with last error logs (exist button at bottom of options)

Запазване на последните грешки във файл на JSON

Save last error logs into JSON file

Възстановяване на група „$grouptitle$“

Undelete a group menu title

Натиснете тук, за да спрете изтриването на група „$grouptitle$“

Click here to cancel the deletion of the group title

Магнитна група

Sticky group

Разделите от тази група няма да бъдат автоматично премествани в друга група

Tabs in this group will never be automatically moved to another group

Пиктограма

Icon style

Освобождаване на памет от скритите раздели

Discard tabs after hide (this will save the RAM)

Групата не може да бъде променяна, защото един от отворените раздели използва микрофон или камера

It is not possible to change the group because one of the opened tabs share microphone or camera

Скрити несинхронизирани раздели. Изберете раздел, за да го добавите в текущата група/прозорец или изберете

Found hidden unsynchronized tabs. Click on tab to show it into current group/window or:

Преместване на всички в текущата група/прозорец

Move all of these tabs into current group/window

Създаване на група с всички

Create new group with all of these tabs

Затваряне на всички

Close all of these tabs

Обновяване на миниатюрата на раздела

Update thumbnail for this tab

Грешка: не са намерени обикновени или поверителни/инкогнито/изскачащи прозорци.
Добавката е спряла да работи. Рестартирайте мрежовия четец.

Error: not found any normal not private/incognito/popup windows.
Addon stopped working. Please, restart browser.

Firefox се срина и всички групи от раздели са загубени.
Ако имате резервно копие възстановете групите от него.

FF failed and all the groups were lost.
If you have a backup, you can restore data from it

Пиктограма на нова група

Icon style for a new group

Отваряне на групата в прозорец

Open group in new window

Заглушаване на разделите при затваряне на групата

Mute tabs when group close and restore when open

Отваряне на раздела след автоматично преместване

Show the tab after auto-moving it into this group

Преместване на раздели

Tab moving

Пиктограми на разделите (увеличава размера на резервното копие)

Include tab fav-icons in backup (makes backup file size bigger)

Групата „$group$“ е премахната от разширението „$extension$“

Group "$group$" removed by extension: $extension$

Грешка, натиснете за презареждане на добавката STG

Something went wrong, click here to reload STG addon

Разширено търсене

Extended search

Преместване на $count$ раздела

Moving $count$ tabs

Закачени раздели не се поддържат

Pinned tabs are not supported

Адресът „$urls$“ не се поддържа

This urls "$urls$" are not supported

Следните раздели не могат да бъдат скрити защото са закачени, използват микрофона, камерата или споделят екрана: „$titles$“

These tabs can not be hidden because they are pinned, using a microphone, camera or shared screen: "$titles$"

$tabscount$ раздела са преместени.
Натиснете тук, за да посетите първия

$tabscount$ tabs has been moved.
Click here to open the first tab

Автоматични резервни копия

Enable auto backup

На всеки

Create backup every:

час(а)

hour(s)

ден(а)

day(s)

Последното копие е от

Last backup:

Тъмна тема

Enable dark theme

За пълна поддръжка на тъмната тема трябва да зададете на свойството
svg.context-properties.content.enabled стойност true в страницата на
about:config

Как да го направя?

Fully support the dark theme text

Възстановяване на „Panorama View“ от photodiode

Restore photodiode's "Panorama View"

Внесете резервно копие от добавката „Panorama View“.

Load a backup file from "Panorama View" addon.

Възстановяване на „Sync Tab Groups“ от Morikko

Restore Morikko's "Sync Tab Groups"

Внесете резервно копие от добавката „Sync Tab Groups“.

Load a backup file from "Sync Tab Groups" addon.

Разглеждане…

Browse...

Отваряне на папката

Open backup folder

Създаване на група при отваряне на прозорец

Create a new group when opening a new window

Добавяне на името на групата към името на прозореца

Prepend group title to window title

Разрешаване на достъпа до отметките

Allow access to bookmarks

Отваряне в група

Open bookmark in group

Отметката е забранена

This bookmark is not allowed

Отваряне в група

Open link in group title

Контекстуално меню на разделите

Show context menu on tabs

Контекстуално меню на препратките

Show context menu on links

Създадени са $groupscount$ групи

Groups created count

Не са създадени групи

No groups created

Добавката няма достъп до отметките. Разрешете достъпа в настройките на добавката

You do not have access to bookmarks. Enable it on in addon settings

Изнасяне на групите в папка „$bookmarkfolder$“ в отметките

Export groups to '$bookmarkfolder$' bookmark folder

Изнасяне на групата в отметките

Export group to bookmarks

Папка от отметките по подразбиране

Default bookmark folder location

Групата „$grouptitle$“ е успешно изнесена в отметките

Group '$grouptitle$' successfully exported to bookmarks

Групата не съдържа раздели

This group has no tabs

Създаване на резервно копие на групите в отметките

Auto backup all groups to bookmarks

Изнасяне на групите в отметките

Export all groups to bookmarks

Всички групи са успешно изнесени в отметките

All groups successfully exported to bookmarks

Освобождаване на памет от раздела

Discard tab

Автоматични резервни копия на групите във файл (в папката за изтегляния)

Auto backup all groups to file (into downloads folder)

Име на папката

Folder name title

Резервното копие е възстановено!

Backup successfully restored

Зареждане, моля изчакайте…

Loading, please wait...

Показване на другите раздели

Show other tabs

Без освобождаване на памет от разделите в групата след смяната ѝ

Don't discard tabs into this group after hide

Показване на известие след изтриване на група

Show notification after group delete

Презареждане на раздела

Reload tab

Този раздел не се поддържа

This tab is not supported

Показване на броя отворени раздели в менюто

Show active tabs in groups popup

Презареждане на разделите в групата

Reload all tabs in group

$tabscount$ раздела създадени

Tabs created count

Не са създадени раздели

Tabs not created

Представяне на сайтовете с миниатюри в страницата „Управление на групите“

Show tabs with thumbnails in "Manage groups" page

Новите разделите се отварят в изолатор

Always open tabs in container

⌚Временен изолатор

⌚Temporary Container

Изолаторът „$containerName$“ вече не е временен

This container '$containerName$' is no longer temporary

Изолаторът „$containerName$“ вече е временен

This container '$containerName$' has now become temporary

Внасяне на настройки

Import addon settings

Внасяне на групи

Import groups

Закачени раздели

Pinned tabs

Това действие ще ЗАЛИЧИ НАПЪЛНО текущите групи и настройки на добавката!
Разделите ще останат непокътнати.

This action will FULL ERASE all existing settings and groups!
Tabs will not be affected.

Изчистване

Clear

Изтриване на данните и настройките на добавката

Delete all addon data and settings

Внимание! ВСИЧКИ данни на добавката ще бъдат заличени. Сигурни ли сте?

Warning! Removing ALL addon data! Are you really sure?

Ако текущия изолатор е различен от избрания, тогава да бъде подменен

If the container is different from the selected one - change the container

Изтриване на всички данни и настройки на добавката преди възстановяване

Delete all addon data and settings before restoring backup

Добре дошли при Simple Tab Groups издание 4

Welcome to Simple Tab Groups v4

Моля, отметнете „Възстановяване на предишната сесия“ в настройките на четеца.
Това е необходимо, за да бъде запазена връзката между групите и разделите
В противен случай при отваряне на четеца разделите няма да бъдат заредени
и ще бъдат недостъпни за добавката и ще спре да работи.

Please enable "Restore previous session" in browser settings.
This is necessary to maintain communication between the group and the tab,
otherwise the tabs will not open when the browser starts and will be lost from the addon -
the addon will stop working.

Welcome to Simple Tab Groups v4

Моля, забранете достъпа на добавката до поверителни прозорци:

Please disable add-on access to private mode in windows:

Включване на режим DEBUG

Enable DEBUG

записване в журнал

logging is enabled

автоматично записване в журнал поради грешка в добавката

logging was auto-enabled due to an error in addon

Моля, отметнете полето само ако трябва да пресъздадете грешка и да изпратите журнала на автора. Отмятането на това поле ще доведе до чувствително намаляване на производителността на добавката, тъй като всички нейни действия се отразяват в журнала. След като успешно пресъздадете грешката махнете отметката и добавката ще ви предложи да запазите журнала във файл. В случай на грешка добавката сама може да отметне това поле. В този случай трябва да махнете отметката и пак да запазите журнала във файл.
Моля, изпратете този файл по имейл на drive4ik+stg@protonmail.com
Внимание! Журналът не съдържа лична информация като пароли, отметки и т.н.
Той е необходим за пресъздаване на проблема и неговото отстраняване от автора.
Поздрави!

logging description

Архивиране

Archive

Разархивиране

Unarchive

Действието не може да бъде изпълнено, защото групата „$grouptitle$“ е архивирана.

Unable to complete the action, the group is in the archive

Моля, обновете добавката до последното ѝ издание.

Please, update addon to latest version

Преименуване на група

Rename group

Няма групи

You have no groups

Питане за име при създаване на група

Always ask for a new group name

Невъзможно е да бъде питано за „$action$“ на страница „$page$“

Научете повече

On page "$page$" it is impossible to ask about "$action$"

Отваря изскачащия прозорец

Open popup

Отваря страничната лента

Open sidebar

Адресът не може да бъде отворен в изолатор

Can't open URL in container

Адресът не може да бъде отворен в изолатор <container-name>$containerName$</container-name>

Can't open the URL into Personal container

добавката не може да отвори адрес:

addon can't open URL:

Групата <strong>$groupTitle$</strong> е настроена да отваря раздели в изолатор <container-name>$containerName$</container-name>

Group 'Group 1' was assigned to open tabs in Personal container.

Друга добавка с UUID:

Another addon, which has UUID:

опитва да да отвори същия адрес в изолатор <container-name>$containerName$</container-name>. Или преместете раздела в друга група, или забранете на добавката <strong>$uuid$</strong> да извършва това действие.

tries to open this URL in Business container. Move the tab to another group or forbid the addon '757eaba7-0b3d-478b-ace2-cbe0a16eed47' to perform this action.

Можете да видите добавките и техните UUID на:

You can find out the addon by UUID on the page:

Отваря в изолатор <container-name>$containerName$</container-name>

Open in Personal container

{'repo_name': 'Drive4ik/simple-tab-groups', 'stars': '403', 'repo_language': 'HTML', 'file_name': 'messages.json', 'mime_type': 'text/plain', 'hash': -683344825564042021, 'source_dataset': 'data'}