Ditto is an extension to the standard windows clipboard. It saves each item placed on the clipboard allowing you access to any of those items at a later time. Ditto allows you to save any type of information that can be put on the clipboard, text, images, html, custom formats, .....
tis-ditto icon


  • package : tis-ditto
  • version :
  • architecture : x64
  • categories : Utilities
  • maintainer : Tranquil IT Systems, BRAYE Benjamin
  • description : Ditto is an extension to the standard windows clipboard. It saves each item placed on the clipboard allowing you access to any of those items at a later time. Ditto allows you to save any type of information that can be put on the clipboard, text, images, html, custom formats, .....
  • locale :
  • target_os : windows
  • min_wapt_version :
  • sources :
  • installed_size : 3211264
  • impacted_process :
  • description_fr :
  • description_pl :
  • description_de :
  • description_es :
  • description_pt :
  • description_it :
  • description_nl :
  • description_ru :
  • editor :
  • licence : GPL
  • signature_date : 2021-12-20T11:01:48.688536
  • Homepage : https://ditto-cp.sourceforge.io/


# -*- coding: utf-8 -*-
from setuphelpers import *
import platform
import json

# Usable WAPT package functions: install(), uninstall(), session_setup(), audit(), update_package()
# Declaring global variables - Warnings: 1) WAPT context is only available in package functions; 2) Global variables are not persistent between calls
bin_contains = 'DittoSetup_64bit'
app_uninstallkey = 'Ditto_is1' 

def install():
    # Declaring local variables
    package_version = control.get_software_version()
    bin_name = glob.glob('*%s*.exe' % bin_contains)[0]

    # Installing the software
    print("Installing: %s" % bin_name)
def update_package():
    # Declaring local variables
    result = False
    proxies = get_proxies()
    bin_name_sub = bin_contains + '-%s.exe'
    if not proxies:
        proxies = get_proxies_from_wapt_console()
    app_name = control.name
    git_repo = 'sabrogden/Ditto'
    url_api = 'https://api.github.com/repos/%s/releases/latest' % git_repo
    if control.architecture == 'x64':
        arch = '64bit'
        arch = '32bit'
    # Getting latest version information from official sources
    print("API used is: %s" % url_api)
    json_load = json.loads(wgets(url_api, proxies=proxies))

    for download in json_load['assets']:
        if bin_contains in download['name']:
            url_dl = download['browser_download_url']
            version = json_load['tag_name'].replace('v', '')
            latest_bin = download['name']

    print("Latest %s version is: %s" % (app_name, version))
    print("Download URL is: %s" % url_dl)

    # Downloading latest binaries
    if not isfile(latest_bin):
        print("Downloading: %s" % latest_bin)
        wget(url_dl, latest_bin, proxies=proxies)

        print("Changing version to the version number of the binary")
        os.rename(latest_bin,bin_name_sub % version)

    # Changing version of the package
    if Version(version) > Version(control.get_software_version()):
        print("Software version updated (from: %s to: %s)" % (control.get_software_version(), Version(version)))
        result = True
    control.version = '%s-%s' % (Version(version), control.version.split('-', 1)[-1])

    # Deleting outdated binaries

    # Validating update-package-sources
    return result

def get_proxies():
    r"""Return system proxy with the urllib python library

    >>> get_proxies()
    {'http': 'http://srvproxy.ad.domain.lan:8080',
    'https': 'http://srvproxy.ad.domain.lan:8080'}

    if platform.python_version_tuple()[0] == '3':
        from urllib.request import getproxies
        from urllib import getproxies
    return getproxies()

def get_proxies_from_wapt_console():
    r"""Return proxy information from the current user WAPT console

    >>> get_proxies_from_wapt_console()
    {'http': 'http://srvproxy.ad.domain.lan:8080',
    'https': 'http://srvproxy.ad.domain.lan:8080'}

    proxies = {}
    if platform.system() == 'Windows':
        waptconsole_ini_path = makepath(user_local_appdata(), 'waptconsole', 'waptconsole.ini')
        waptconsole_ini_path = makepath(user_home_directory(), '.config', 'waptconsole', 'waptconsole.ini')
    if isfile(waptconsole_ini_path):
        proxy_wapt = inifile_readstring(waptconsole_ini_path, 'global', 'http_proxy')
        if proxy_wapt:
            proxies = {'http': proxy_wapt, 'https': proxy_wapt}
    return proxies

def get_version_from_binary(filename, property_name='ProductVersion'):
    r""" Get installer version from file informations, for now, only exe and msi files are compatibles

        filename (str): path to the file
        property_name (str): selected property

        str: version number

    if filename.endswith('.msi'):
        return get_msi_properties(filename)[property_name]
        return get_file_properties(filename)[property_name]

def remove_outdated_binaries(version, filename_contains=None, list_extensions=['exe','msi','deb','rpm','dmg','pkg']):
    r"""Remove files based on the version contained in his filename

        version (str): version number of keeped files
        filename_contains (str or list of str): Part of the filename that must be contained (useful for distinguishing architecture and os)
        list_extensions (str or list of str): file extensions of verified files


    .. versionadded:: 2.0

    if type(list_extensions) != list:
        list_extensions = [list_extensions]
    if filename_contains:
        if type(filename_contains) != list:
            filename_contains = [filename_contains]
    list_extensions = ['.' + ext for ext in list_extensions if ext[0] != '.']
    for file_ext in list_extensions:
        for bin_in_dir in glob.glob('*%s' % file_ext):
            if not version in bin_in_dir:
            if filename_contains:
                for filename_contain in filename_contains:
                    if not filename_contain in bin_in_dir:


  Changelog 12-23-2018

    Fixed crash in latest windows 10 when changing dpi
    Removed message box when we fail to request a file from a remote computer, changed to balloon message in the task tray
    Added option to invert case special paste
    Updated German language file
    Updated to latest version of SQLite, 3.26.
    Added warning message box on compact and repair button is clicked
    Aggregate multiple clips better if some clips don't have all the data needed
    Updated chocolatey portable install script to handle upgrades
    Changed output debug string and output debug to file shortcuts to ctrl-d, ctrl-o and ctrl-d, ctrl-f
    Added back in auto roll-up quick option
    Fixed issue resizing description window with image and then not being able to move next/prev with up/down keys
    Changed right click menu from "filter on" to "filter on selected clip"
    Added export to email, content as attachment Added special paste - slugify
    Fixed import message window size
    Update menu for export to email
    Fixed issue with clicking on an image in description window and the up/down arrows stop working
    Added email to and gmail export options
    Trim include/exclude app text when checking against current app
    Added Hungarian language file
    When the desktop has focus center over the screen with the mouse cursor
    Handle ensure window is visible on differnt dpi monitors better