diff --git a/.coafile b/.coafile
new file mode 100644
index 0000000..9ea388c
--- /dev/null
+++ b/.coafile
@@ -0,0 +1,21 @@
+[all]
+ignore = **/build/**
+
+[all.vala]
+bears = SpaceConsistencyBear, FilenameBear
+files = **.vala
+use_spaces = True
+file_naming_convention = pascal
+
+[all.xml]
+bears = XMLBear
+files = **.(ui|xml)
+
+[all.git]
+bears = GitCommitBear
+shortlog_length = 79
+shortlog_regex = ^VENOM-\d+: .*
+
+[all.po]
+bears = DennisBear
+files = **.(po|pot)
diff --git a/.gitignore b/.gitignore
index f2c24e3..a2410a9 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,8 +1,6 @@
*~
-icons/CMakeFiles
-icons/Makefile
-icons/cmake_install.cmake
-theme/CMakeFiles
-theme/Makefile
-theme/cmake_install.cmake
build
+
+# GNOME Builder
+.buildconfig
+.flatpak-builder
diff --git a/.travis.yml b/.travis.yml
index d6a547c..698b0ed 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -1,60 +1,15 @@
-language: c
-compiler:
- - gcc
+sudo: required
+language: generic
+services: [docker]
-before_install:
- - sudo apt-add-repository -y ppa:vala-team/ppa
- - sudo apt-get update -qq > /dev/null
- - sudo apt-get install -qq valac cmake libgtk-3-dev check libjson-glib-dev libsqlite3-dev yasm libqrencode-dev libnotify-dev > /dev/null
-
-before_script:
- #installing libsodium, needed for Core
- - _libsodium_ver=0.7.0
- - git clone git://github.com/jedisct1/libsodium.git > /dev/null
- - pushd libsodium
- - git checkout tags/${_libsodium_ver} > /dev/null
- - ./autogen.sh > /dev/null
- - ./configure --prefix=/usr > /dev/null
- - make -j3 > /dev/null
- - sudo make install > /dev/null
- - popd
- #installing libopus, needed for audio encoding/decoding
- - _opus_ver=1.0.3
- - wget http://downloads.xiph.org/releases/opus/opus-${_opus_ver}.tar.gz > /dev/null
- - tar xzf opus-${_opus_ver}.tar.gz > /dev/null
- - pushd opus-${_opus_ver}
- - ./configure --prefix=/usr > /dev/null
- - make -j3 > /dev/null
- - sudo make install > /dev/null
- - popd
- #installing vpx
- - git clone http://git.chromium.org/webm/libvpx.git > /dev/null
- - pushd libvpx
- - ./configure --prefix=/usr --enable-shared > /dev/null
- - make -j3 > /dev/null
- - sudo make install > /dev/null
- - popd
- #installing toxcore
- - git clone http://github.com/irungentoo/ProjectTox-Core.git > /dev/null
- - pushd ProjectTox-Core
- - autoreconf -i > /dev/null
- - ./configure --prefix=/usr --disable-ntox --disable-daemon > /dev/null
- - make -j3 > /dev/null
- - sudo make install > /dev/null
- - popd
- #compiling djbdns needed for glib < 2.34
- - wget http://cr.yp.to/djbdns/djbdns-1.05.tar.gz
- - tar -xzf djbdns-1.05.tar.gz
- - pushd djbdns-1.05
- - echo gcc -O2 -include /usr/include/errno.h > conf-cc
- - make
- - popd
- #creating libraries links and updating cache
- - sudo ldconfig > /dev/null
+install:
+ - docker build --tag test-image .
+ - docker run --detach --interactive --name test-image-container --volume "$(pwd)":/tmp/venom --workdir /tmp/venom test-image
script:
- - mkdir build
- - cd build
- - cmake -DDJBDNS_DIRECTORY="../djbdns-1.05" -DENABLE_QR_ENCODE=ON -DENABLE_LIBNOTIFY=ON ..
- - make -j3
- - sudo make install
+ - docker exec test-image-container meson -D b_coverage=true build
+ - docker exec test-image-container ninja -C build
+ - docker exec test-image-container ninja -C build test
+
+after_success:
+ - bash <(curl -s https://codecov.io/bash)
diff --git a/AUTHORS b/AUTHORS
index 7973c25..40bc8d8 100644
--- a/AUTHORS
+++ b/AUTHORS
@@ -1,7 +1 @@
-See https://github.com/naxuroqa/Venom for a list of contributors.
-
-venom_faenza.svg is styled after Matthieu James' Faenza icon theme.
-See http://tiheum.deviantart.com/art/Faenza-Icons-173323228.
-
-venom.svg/venom.png and venom_numix.svg are styled after numixproject's numix icon theme.
-See https://github.com/numixproject/numix-icon-theme.
+See https://github.com/naxuroqa/Venom/graphs/contributors for a list of contributors.
diff --git a/CMakeLists.txt b/CMakeLists.txt
deleted file mode 100644
index 51f9437..0000000
--- a/CMakeLists.txt
+++ /dev/null
@@ -1,84 +0,0 @@
-#
-# Copyright (C) 2013-2014 Venom authors and contributors
-#
-# This file is part of Venom.
-#
-# Venom is free software: you can redistribute it and/or modify
-# it under the terms of the GNU General Public License as published by
-# the Free Software Foundation, either version 3 of the License, or
-# (at your option) any later version.
-#
-# Venom is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with Venom. If not, see .
-#
-
-CMAKE_MINIMUM_REQUIRED(VERSION 2.8.7)
-PROJECT(Venom C)
-
-LIST(APPEND CMAKE_MODULE_PATH ${CMAKE_SOURCE_DIR}/cmake)
-
-SET(VENOM_VERSION_MAJOR 0)
-SET(VENOM_VERSION_MINOR 2)
-SET(VENOM_VERSION_PATCH 0)
-SET(VENOM_VERSION_RELEASE "" CACHE STRING "")
-SET(VENOM_VERSION
- ${VENOM_VERSION_MAJOR}.${VENOM_VERSION_MINOR}.${VENOM_VERSION_PATCH}${VENOM_VERSION_RELEASE})
-SET(VENOM_COPYRIGHT_NOTICE "Copyright © 2013-2014 Venom authors and contributors")
-SET(VENOM_SHORT_DESCRIPTION "GTK+/Vala GUI for Tox")
-SET(VENOM_WEBSITE "https://github.com/naxuroqa/Venom")
-
-MESSAGE("Venom version ${VENOM_VERSION}")
-
-OPTION( FORCE_32BIT "Set to ON to force 32bit build" OFF )
-OPTION( BUILD_STATIC_EXECUTABLES "" OFF)
-OPTION( ENABLE_QR_ENCODE "Set to ON to enable QR codes" OFF )
-OPTION( ENABLE_DJBDNS "Set to ON to use djbdns to resolve tox dns ids (mandatory for glib <= 2.32)" OFF )
-
-#check architecture
-IF(CMAKE_SIZEOF_VOID_P EQUAL 8)
- IF(FORCE_32BIT)
- MESSAGE("32 bit architecture forced.")
- SET(ARCHITECTURE 32)
- SET_PROPERTY(GLOBAL PROPERTY FIND_LIBRARY_USE_LIB64_PATHS 0)
- SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -m32")
- ELSE(FORCE_32BIT)
- MESSAGE("64 bit architecture detected.")
- SET(ARCHITECTURE 64)
- ENDIF(FORCE_32BIT)
-ELSE(CMAKE_SIZEOF_VOID_P EQUAL 8)
- MESSAGE("32 bit architecture detected.")
- SET(ARCHITECTURE 32)
-ENDIF(CMAKE_SIZEOF_VOID_P EQUAL 8)
-
-#put binary in root on windows
-IF(WIN32)
- SET(CMAKE_INSTALL_SYSTEM_RUNTIME_DESTINATION .)
-ELSE(WIN32)
- SET(CMAKE_INSTALL_SYSTEM_RUNTIME_DESTINATION bin)
-ENDIF(WIN32)
-
-SET(COMMON_DATA_DIR share)
-
-#Check for Vala
-find_package(Vala REQUIRED)
-
-#i18n
-INCLUDE(Gettext)
-SET(GETTEXT_PACKAGE "Venom")
-#FIXME make this work for portable installations at runtime
-SET(GETTEXT_PATH "${CMAKE_INSTALL_PREFIX}/${COMMON_DATA_DIR}/locale")
-
-ADD_SUBDIRECTORY(misc)
-ADD_SUBDIRECTORY(icons)
-ADD_SUBDIRECTORY(theme)
-ADD_SUBDIRECTORY(src)
-ADD_SUBDIRECTORY(po)
-
-INCLUDE(CPackDefines)
-
-# vim:set ts=2 sw=2 et:
diff --git a/ChangeLog b/ChangeLog
deleted file mode 120000
index 3d70ee3..0000000
--- a/ChangeLog
+++ /dev/null
@@ -1 +0,0 @@
-NEWS
\ No newline at end of file
diff --git a/Dockerfile b/Dockerfile
new file mode 100644
index 0000000..7e20ec7
--- /dev/null
+++ b/Dockerfile
@@ -0,0 +1,29 @@
+FROM debian:sid
+
+RUN \
+ apt-get update && \
+ apt-get -y upgrade && \
+ apt-get install -y \
+ build-essential \
+ cmake \
+ libgtk-3-dev \
+ libjson-glib-dev \
+ libopus-dev \
+ libsodium-dev \
+ libsoup2.4-dev \
+ libsqlite3-dev \
+ libvpx-dev \
+ libgee-0.8-dev \
+ meson \
+ valac \
+ wget
+
+RUN rm -rf /var/lib/apt/lists/*
+
+RUN wget "https://github.com/TokTok/c-toxcore/archive/v0.2.2.tar.gz" && \
+ tar -xzf v0.2.2.tar.gz && \
+ cd c-toxcore-0.2.2 && \
+ cmake -DCMAKE_INSTALL_PREFIX=/usr && \
+ make && \
+ make install && \
+ cd ..
diff --git a/INSTALL b/INSTALL
deleted file mode 120000
index 13dc419..0000000
--- a/INSTALL
+++ /dev/null
@@ -1 +0,0 @@
-INSTALL.md
\ No newline at end of file
diff --git a/INSTALL.md b/INSTALL.md
deleted file mode 100644
index ac4bb0c..0000000
--- a/INSTALL.md
+++ /dev/null
@@ -1,138 +0,0 @@
-Installation
-============
-- [Linux](#linux)
-- [OS X](#os-x)
-- [Windows](#windows)
-- [FAQ](#faq)
-
-Linux
-=====
-
-Follow ProjectTox-Core [installation instructions](https://github.com/irungentoo/ProjectTox-Core/blob/master/INSTALL.md#linux).
-Don't forget to install it after building it.
-
-Dependencies
-------------
-
-Additionally to the tox build dependencies, you will need:
-
-| Package name | Version | Comment |
-|------------------|-----------|----------------|
-| valac | >=0.18.1 | |
-| cmake | >=2.8.7 | |
-| libgtk-3-dev | >=3.4 | |
-| libjson-glib-dev | >=0.14 | |
-| libsqlite3-dev | >=3.7 | |
-| libnotify-dev | >=0.7.3 | optional, *nix |
-| libqrencode-dev | >=3.1.1 | optional, *nix |
-| djbdns | ? | optional, *nix |
-
-
-Ubuntu >= 12.10 (Quantal Quetzal) / Linux Mint / Debian:
-
- apt-get install valac cmake libgtk-3-dev libjson-glib-dev libsqlite3-dev libqrencode-dev libnotify-dev
-
-Ubuntu 12.04 (Precise Pangolin): (needs a ppa to get a newer version of valac as well as djbdns for dns resolution)
-
- apt-add-repository ppa:vala-team/ppa
- apt-get update
- apt-get install valac cmake libgtk-3-dev libjson-glib-dev libsqlite3-dev libqrencode-dev libnotify-dev
-
-Fedora:
-
- yum install vala cmake gtk3-devel json-glib-devel sqlite-devel qrencode-devel libnotify-devel
-
-Arch Linux: (There is an [aur-package](https://aur.archlinux.org/packages/venom-git))
-
- pacman -S vala cmake gtk3 json-glib sqlite qrencode libnotify
-
-Building and installing Venom
------------------------------
-
-If your version of glib is smaller than 2.34, you will need djbdns to resolve dns entries:
-
- wget http://cr.yp.to/djbdns/djbdns-1.05.tar.gz
- tar -xzf djbdns-1.05.tar.gz
- cd djbdns-1.05
- echo gcc -O2 -include /usr/include/errno.h > conf-cc
- make
-
-After you installed the dependencies, clone, build and install venom:
-
- git clone git://github.com/naxuroqa/Venom.git
- cd Venom
- mkdir build
- cd build
- # For glib >= 2.34
- cmake ..
- # or for glib 2.32
- cmake -DDJBDNS_DIRECTORY="" ..
- make
- sudo make install
-
-OS X
-====
-
-Follow ProjectTox-Core [installation instructions](https://github.com/irungentoo/ProjectTox-Core/blob/master/INSTALL.md#os-x).
-
-With Homebrew
--------------
-
- brew tap Tox/tox
- brew install --HEAD libtoxcore
- brew install --HEAD venom
-
-Windows
-=======
-
-The preferred way is to cross compile windows binaries from linux using the mingw-w64 toolchain.
-
-Cross compile (mingw-w64)
--------------------------
-
-###Dependencies
-* Set up a mingw-w64 toolchain
-* build ffmpeg (optionally for now)
-* build libsodium
-* build libtoxcore
-* build gtk+-3.x
-* build libjson-glib
-* build libsqlite3
-
-There is an [aur-package](https://aur.archlinux.org/packages/mingw-w64-venom-git) for arch linux, which automates the build process.
-
-###Compiling Venom
-
- git clone git://github.com/naxuroqa/Venom.git
- cd Venom
- mkdir build
- cd build
- PKG_CONFIG_PATH=/usr//lib/pkgconfig
- # you may have to adapt the mingw-toolchain.cmake file for your cross compiler prefix
- cmake -DCMAKE_C_FLAGS="-mwindows" \
- -DCOMPILER_PREFIX= \
- -DCMAKE_TOOLCHAIN_FILE=../cmake/mingw-toolchain.cmake \
- -DCMAKE_BUILD_TYPE="Release" ..
- make
- sudo make install
-
-FAQ
-===
-#### Cmake complaining about missing modules
-If you are getting errors like these when running cmake
-
- -- checking for module ''
- -- package '' not found
- CMake Error at /usr/share/cmake-2.8/Modules/FindPkgConfig.cmake:279 (message):
- A required package was not found
- Call Stack (most recent call first):
- /usr/share/cmake-2.8/Modules/FindPkgConfig.cmake:333 (_pkg_check_modules_internal)
- CMakeLists.txt:30 (PKG_CHECK_MODULES)
-
-then cmake can't find one or more dependencies needed to build Venom.
-
-Make sure, that you have all dependencies mentioned above installed.
-If you used a different prefix than ``/usr`` to install libtoxcore, you will need to tell it cmake here.
-You do this by setting ``PKG_CONFIG_PATH=//lib/pkgconfig`` and running cmake again.
-
-See also the solutions to [issue #4](https://github.com/naxuroqa/Venom/issues/4) and [issue #12](https://github.com/naxuroqa/Venom/issues/12)
diff --git a/NEWS b/NEWS
deleted file mode 100644
index ed26b88..0000000
--- a/NEWS
+++ /dev/null
@@ -1,16 +0,0 @@
-Venom: A GTK+ GUI for Tox written in Vala
-
-v0.2.0 WIP
- * Filetransfer support
- * Config file
- * Chat log (turned off by default)
- * NSIS installer available for windows (needed for handling uris)
- * Single instance (needed for handling uris)
- * tox:// URI support
- * Filter online contacts/groupchats
- * Groupchat support
- * Action support
-
-v0.1.2 06.10.2013
-v0.1.1 02.10.2013
-v0.1.0 01.10.2013
diff --git a/README b/README
deleted file mode 120000
index 42061c0..0000000
--- a/README
+++ /dev/null
@@ -1 +0,0 @@
-README.md
\ No newline at end of file
diff --git a/README.md b/README.md
index d031175..3e478e3 100644
--- a/README.md
+++ b/README.md
@@ -1,27 +1,65 @@
-Venom [![Build Status](https://travis-ci.org/naxuroqa/Venom.png?branch=master)](https://travis-ci.org/naxuroqa/Venom) [![tip for next commit](http://tip4commit.com/projects/634.svg)](http://tip4commit.com/projects/634)
+Venom
=====
-a cross-platform graphical user interface for [Tox](https://github.com/irungentoo/ProjectTox-Core) written in [Vala](https://wiki.gnome.org/Vala) using [GTK+](http://gtk.org).
+[![Build Status](https://travis-ci.org/naxuroqa/Venom.png?branch=develop)](https://travis-ci.org/naxuroqa/Venom) [![tip for next commit](http://tip4commit.com/projects/634.svg)](http://tip4commit.com/projects/634) [![codecov](https://codecov.io/gh/naxuroqa/Venom/branch/develop/graph/badge.svg)](https://codecov.io/gh/naxuroqa/Venom)
-Installing
-----------
+###### a modern [Tox](https://github.com/TokTok/c-toxcore) client for the Linux desktop
-- Grab a [stable](https://github.com/naxuroqa/Venom/releases) or [nightly](https://wiki.tox.im/Binaries)
+Features
+--------
-Contributing
+* Secure, private messaging
+* Read receipts
+* Contact aliases
+* Customizable avatars
+* Emojis 👍
+* File transfers
+* Screenshot sharing
+* Group chats
+* Socks5 Proxy support
+
+Roadmap
+-------
+
+See [projects](https://github.com/naxuroqa/Venom/projects) for planned features.
+
+Translations
------------
-- Implement something from the [TODO](TODO) file
-- Suggest new features
-- Run Venom on your platform and [create a new Issue](https://github.com/naxuroqa/Venom/issues/new) for found errors
+Translations are done via the [venom project on poeditor](https://poeditor.com/join/project/5weMhrvGjN).
+Don't create pull requests for translations here. Updated translations from poeditor will be merged in this repository on every release.
-Contact
+Dependencies
+------------
+
+* `gtk+-3.0 >= 3.22`
+* `glib-2.0 >= 2.56`
+* `json-glib-1.0`
+* `libsoup-2.4`
+* `libgee >= 0.20`
+* `sqlite3`
+* `toxcore >= 0.2`
+
+Build-Dependencies
+------------------
+* `meson >= 0.46`
+* `vala >= 0.40`
+
+Compiling
+---------
+```bash
+meson ./build && cd build
+ninja
+ninja install
+```
+
+Testing
-------
-- Visit our IRC channel `#tox` on [freenode](https://freenode.net/)
-[![Visit our IRC channel](https://kiwiirc.com/buttons/irc.freenode.net/tox.png)](https://kiwiirc.com/client/irc.freenode.net/?theme=basic#tox)
-- write an email to [naxuroqa@gmail.com](mailto:naxuroqa@gmail.com)
+```bash
+ninja test
+```
-License
+Contact
-------
-Venom is licensed under [GPLv3](COPYING).
+Join the `#tox` IRC channel on [freenode](https://freenode.net/)
diff --git a/TODO b/TODO
deleted file mode 100644
index 8e457c5..0000000
--- a/TODO
+++ /dev/null
@@ -1,23 +0,0 @@
-[0.2]
-* save actions in db
-* testing
-
-[0.3]
-* add audiochat
-* add videochat
-
-[0.4]
-* Local storage additionally to tox data file (sqlite, plain xml file, ...?)
- * add local nicknames/tags for contacts (optionally)
- * make dht boostrapping nodes editable / selectable
-
-[future]
-* add option for multiaccount
-* unit tests
-* test it on OSX
-* add plugins
- * sound plugin
- * inotify plugin
- * logger plugin
- * anonymizer plugin (strip metadata of known media)
- * ...
diff --git a/chat.tox.venom.yml b/chat.tox.venom.yml
new file mode 100644
index 0000000..7d39595
--- /dev/null
+++ b/chat.tox.venom.yml
@@ -0,0 +1,59 @@
+app-id: chat.tox.venom
+runtime: org.gnome.Platform
+runtime-version: '3.28'
+sdk: org.gnome.Sdk
+command: venom
+tags: [nightly]
+desktop-file-name-prefix: (Nightly)
+finish-args:
+ - --share=network
+ - --socket=x11
+ - --share=ipc
+ - --socket=wayland
+ - --device=dri
+ - --socket=pulseaudio
+ - --talk-name=ca.desrt.dconf
+ - --talk-name=org.freedesktop.Notifications
+ - --filesystem=xdg-data/pixmaps/faces:ro
+ - --filesystem=xdg-download
+build-options:
+ cflags: -O2 -g
+ cxxflags: -O2 -g
+ env:
+ V: '1'
+modules:
+ - name: libgee
+ build-options:
+ env:
+ PKG_CONFIG_GOBJECT_INTROSPECTION_1_0_GIRDIR: /app/share/gir-1.0
+ PKG_CONFIG_GOBJECT_INTROSPECTION_1_0_TYPELIBDIR: /app/lib/girepository-1.0
+ sources:
+ - type: git
+ url: https://git.gnome.org/browse/libgee
+ tag: 0.20.1
+ commit: 57e4c8a08d61ab77bbec310a3a1621e6bf3111cb
+ - name: libsodium
+ sources:
+ - type: git
+ url: https://github.com/jedisct1/libsodium
+ tag: 1.0.16
+ commit: 675149b9b8b66ff44152553fb3ebf9858128363d
+ - name: toxcore
+ buildsystem: cmake
+ config-opts:
+ - -DCMAKE_BUILD_TYPE=Release
+ - -DENABLE_STATIC=OFF
+ sources:
+ - type: git
+ url: https://github.com/toktok/c-toxcore
+ tag: v0.2.2
+ commit: 2824daf74a6d2bd60ebaf387a30f1b7719b6b67c
+ - name: venom
+ builddir: true
+ buildsystem: meson
+ config-opts:
+ - --buildtype=debugoptimized
+ sources:
+ - type: git
+ url: https://github.com/naxuroqa/Venom
+ branch: develop
diff --git a/cmake/CPackDefines.cmake b/cmake/CPackDefines.cmake
deleted file mode 100644
index 2693b64..0000000
--- a/cmake/CPackDefines.cmake
+++ /dev/null
@@ -1,132 +0,0 @@
-#
-# Copyright (C) 2013 Venom authors and contributors
-#
-# This file is part of Venom.
-#
-# Venom is free software: you can redistribute it and/or modify
-# it under the terms of the GNU General Public License as published by
-# the Free Software Foundation, either version 3 of the License, or
-# (at your option) any later version.
-#
-# Venom is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with Venom. If not, see .
-#
-# CPACK_NSIS_EXTRA_* protocol register and unregister macros from
-# http://hg.pidgin.im/pidgin/main/file/tip/pidgin/win32/nsis/pidgin-installer.nsi
-# Original Author: Herman Bloggs
-# Updated By: Daniel Atallah
-
-IF(WIN32)
- IF(NOT EXISTS "${CMAKE_CURRENT_BINARY_DIR}/libsodium_license.txt")
- FILE(
- DOWNLOAD
- "https://raw.github.com/jedisct1/libsodium/master/LICENSE"
- "${CMAKE_CURRENT_BINARY_DIR}/libsodium_license.txt"
- )
- ENDIF()
- INSTALL(
- FILES
- "${CMAKE_CURRENT_BINARY_DIR}/libsodium_license.txt"
- DESTINATION
- "${COMMON_DATA_DIR}/licenses/libsodium"
- RENAME
- LICENSE
- )
- FILE(GLOB WIN32LIBS "${CMAKE_CURRENT_BINARY_DIR}/win32libs/*.dll")
- SET(CMAKE_INSTALL_SYSTEM_RUNTIME_LIBS ${WIN32LIBS})
- INCLUDE(InstallRequiredSystemLibraries)
-ENDIF(WIN32)
-
-# architecure specific stuff
-IF(ARCHITECTURE EQUAL 32)
- SET(CPACK_NSIS_INSTALL_ROOT "$PROGRAMFILES")
- SET(CPACK_DEBIAN_PACKAGE_ARCHITECTURE i386)
- SET(CPACK_RPM_PACKAGE_ARCHITECTURE i686)
-ELSE(ARCHITECTURE EQUAL 32)
- SET(CPACK_NSIS_INSTALL_ROOT "$PROGRAMFILES64")
- SET(CPACK_DEBIAN_PACKAGE_ARCHITECTURE amd64)
- SET(CPACK_RPM_PACKAGE_ARCHITECTURE x86_64)
-ENDIF(ARCHITECTURE EQUAL 32)
-
-# optional features
-IF(${ENABLE_QR_ENCODE})
- SET(DEBIAN_PACKAGE_DEPENDS_OPT "${DEBIAN_PACKAGE_DEPENDS_OPT}, libqrencode3 (>=3.1.1)")
- SET(RPM_PACKAGE_DEPENDS_OPT "${RPM_PACKAGE_DEPENDS_OPT}, qrencode-libs >= 3.1.1")
-ENDIF()
-
-IF(${ENABLE_LIBNOTIFY})
- SET(DEBIAN_PACKAGE_DEPENDS_OPT "${DEBIAN_PACKAGE_DEPENDS_OPT}, libnotify4 (>= 0.7.3)")
- SET(RPM_PACKAGE_DEPENDS_OPT "${RPM_PACKAGE_DEPENDS_OPT}, libnotify >= 0.7.3")
-ENDIF()
-
-# Basic settings
-SET(CPACK_PACKAGE_DESCRIPTION_SUMMARY "${VENOM_SHORT_DESCRIPTION}")
-SET(CPACK_PACKAGE_EXECUTABLES "venom;Venom")
-SET(CPACK_PACKAGE_INSTALL_DIRECTORY "Venom")
-SET(CPACK_PACKAGE_NAME "Venom")
-SET(CPACK_PACKAGE_VERSION_MAJOR "${VENOM_VERSION_MAJOR}")
-SET(CPACK_PACKAGE_VERSION_MINOR "${VENOM_VERSION_MINOR}")
-SET(CPACK_PACKAGE_VERSION_PATCH "${VENOM_VERSION_PATCH}")
-SET(CPACK_SOURCE_IGNORE_FILES /build/;\\\\.gitignore;.*~;\\\\.git;CMakeFiles;Makefile;cmake_install\\\\.cmake)
-SET(CPACK_SOURCE_STRIP_FILES TRUE)
-SET(CPACK_STRIP_FILES TRUE)
-
-# Advanced
-SET(CPACK_RESOURCE_FILE_LICENSE "${CMAKE_SOURCE_DIR}/COPYING")
-SET(CPACK_RESOURCE_FILE_README "${CMAKE_SOURCE_DIR}/README")
-SET(CPACK_PACKAGE_VERSION "${VENOM_VERSION}")
-SET(CPACK_PACKAGE_DESCRIPTION_FILE "${CMAKE_SOURCE_DIR}/misc/pkgdesc.txt")
-# default: "Humanity", overwrite if needed
-#SET(CPACK_PACKAGE_VENDOR "")
-
-# nsis
-# There is a bug in NSI that does not handle full unix paths properly. Make
-# sure there is at least one set of four (4) backslashes.
-SET(CPACK_NSIS_EXECUTABLES_DIRECTORY ${CMAKE_INSTALL_SYSTEM_RUNTIME_DESTINATION})
-SET(CPACK_NSIS_MUI_ICON "${CMAKE_SOURCE_DIR}\\\\misc\\\\venom.ico")
-SET(CPACK_NSIS_MUI_UNIICON "${CMAKE_SOURCE_DIR}\\\\misc\\\\venom.ico")
-SET(CPACK_PACKAGE_ICON "${CMAKE_SOURCE_DIR}\\\\icons\\\\48x48\\\\venom.png")
-SET(CPACK_NSIS_INSTALLED_ICON_NAME "venom.exe")
-SET(CPACK_NSIS_DISPLAY_NAME "Venom")
-SET(CPACK_NSIS_HELP_LINK "${VENOM_WEBSITE}")
-SET(CPACK_NSIS_URL_INFO_ABOUT "${VENOM_WEBSITE}")
-SET(CPACK_NSIS_CONTACT "naxuroqa@gmail.com")
-SET(CPACK_NSIS_MUI_FINISHPAGE_RUN "venom.exe")
-SET(CPACK_NSIS_EXTRA_INSTALL_COMMANDS "
-;Register the URI handler
-DetailPrint \\\"Registering tox URI Handler\\\"
-DeleteRegKey HKCR \\\"tox\\\"
-WriteRegStr HKCR \\\"tox\\\" \\\"\\\" \\\"URL:tox\\\"
-WriteRegStr HKCR \\\"tox\\\" \\\"URL Protocol\\\" \\\"\\\"
-WriteRegStr HKCR \\\"tox\\\\DefaultIcon\\\" \\\"\\\" \\\"$INSTDIR\\\\venom.exe\\\"
-WriteRegStr HKCR \\\"tox\\\\shell\\\" \\\"\\\" \\\"\\\"
-WriteRegStr HKCR \\\"tox\\\\shell\\\\Open\\\" \\\"\\\" \\\"\\\"
-WriteRegStr HKCR \\\"tox\\\\shell\\\\Open\\\\command\\\" \\\"\\\" \\\"$INSTDIR\\\\venom.exe %1\\\"
-")
-SET(CPACK_NSIS_EXTRA_UNINSTALL_COMMANDS "
-;Unregister the URI handler
-DetailPrint \\\"Unregistering tox URI Handler\\\"
-DeleteRegKey HKCR \\\"tox\\\"
-")
-# .deb
-# libtoxcore ommitted, since we are most likely linking it statically
-SET(CPACK_DEBIAN_PACKAGE_DEPENDS "libgtk-3-0 (>= 3.4.1), libjson-glib-1.0-0 (>= 0.14.2), libsqlite3-0 (>= 3.7.9) ${DEBIAN_PACKAGE_DEPENDS_OPT}")
-SET(CPACK_DEBIAN_PACKAGE_PRIORITY "optional")
-SET(CPACK_DEBIAN_PACKAGE_SECTION "web")
-SET(CPACK_DEBIAN_PACKAGE_HOMEPAGE "${VENOM_WEBSITE}")
-
-# .rpm
-SET(CPACK_RPM_PACKAGE_LICENSE "GPLv3")
-SET(CPACK_RPM_PACKAGE_GROUP "Applications/Internet")
-SET(CPACK_RPM_PACKAGE_REQUIRES "gtk3 >= 3.4.1, json-glib >= 0.14.2, sqlite >= 3.7.9 ${RPM_PACKAGE_DEPENDS_OPT}")
-# Default: some cpack comment, overwrite if needed
-#SET(CPACK_RPM_CHANGELOG_FILE "")
-SET(CPACK_RPM_PACKAGE_RELEASE 1)
-SET(CPACK_RPM_PACKAGE_URL "${VENOM_WEBSITE}")
-
-INCLUDE(CPack)
diff --git a/cmake/FindDJBDns.cmake b/cmake/FindDJBDns.cmake
deleted file mode 100644
index 2ee1648..0000000
--- a/cmake/FindDJBDns.cmake
+++ /dev/null
@@ -1,92 +0,0 @@
-# - Try to find LibDJBCns
-
-#
-# Copyright (C) 2013-2014 Venom authors and contributors
-#
-# This file is part of Venom.
-#
-# Venom is free software: you can redistribute it and/or modify
-# it under the terms of the GNU General Public License as published by
-# the Free Software Foundation, either version 3 of the License, or
-# (at your option) any later version.
-#
-# Venom is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with Venom. If not, see .
-#
-
-# Once done this will define
-# DJBDNS_FOUND - System has djbdns
-# DJBDNS_INCLUDE_DIRS - The djbdns include directories
-# DJBDNS_LIBRARIES - The libraries needed to use djbdns
-
-IF(DJBDNS_LIBRARIES AND DJBDNS_INCLUDE_DIRS)
- # in cache already
- SET(DJBDNS_FOUND TRUE)
-ELSE(DJBDNS_LIBRARIES AND DJBDNS_INCLUDE_DIRS)
- SET(DJBDNS_DIRECTORY "" CACHE PATH "Set a directory to search for DJBDNS libraries and headers")
- FIND_PATH(DJBDNS_LIBRARY_DIR
- NAMES dns.a
- PATHS
- /usr/lib
- /usr/local/lib
- ${DJBDNS_DIRECTORY}
- )
- FIND_PATH(DJBDNS_INCLUDE_DIR
- NAMES dns.h
- PATHS
- /usr/include
- /usr/local/include
- ${DJBDNS_DIRECTORY}
- )
- FIND_FILE(DJBDNS_IOPAUSE_OBJECT
- NAMES iopause.o
- PATHS ${DJBDNS_LIBRARY_DIR}
- )
- FIND_LIBRARY(DJBDNS_DNS_LIBRARY
- NAMES dns.a
- PATHS ${DJBDNS_LIBRARY_DIR}
- )
- FIND_LIBRARY(DJBDNS_ENV_LIBRARY
- NAMES env.a
- PATHS ${DJBDNS_LIBRARY_DIR}
- )
- FIND_LIBRARY(DJBDNS_LIBTAI_LIBRARY
- NAMES libtai.a
- PATHS ${DJBDNS_LIBRARY_DIR}
- )
- FIND_LIBRARY(DJBDNS_ALLOC_LIBRARY
- NAMES alloc.a
- PATHS ${DJBDNS_LIBRARY_DIR}
- )
- FIND_LIBRARY(DJBDNS_BUFFER_LIBRARY
- NAMES buffer.a
- PATHS ${DJBDNS_LIBRARY_DIR}
- )
- FIND_LIBRARY(DJBDNS_UNIX_LIBRARY
- NAMES unix.a
- PATHS ${DJBDNS_LIBRARY_DIR}
- )
- FIND_LIBRARY(DJBDNS_BYTE_LIBRARY
- NAMES byte.a
- PATHS ${DJBDNS_LIBRARY_DIR}
- )
- SET(DJBDNS_LIBRARIES
- ${DJBDNS_IOPAUSE_OBJECT}
- ${DJBDNS_DNS_LIBRARY}
- ${DJBDNS_ENV_LIBRARY}
- ${DJBDNS_LIBTAI_LIBRARY}
- ${DJBDNS_ALLOC_LIBRARY}
- ${DJBDNS_BUFFER_LIBRARY}
- ${DJBDNS_UNIX_LIBRARY}
- ${DJBDNS_BYTE_LIBRARY}
- ${DJBDNS_SOCKET_LIBRARY}
- )
- SET(DJBDNS_INCLUDE_DIRS ${DJBDNS_INCLUDE_DIR})
- SET(DJBDNS_CFLAGS "-I${DJBDNS_INCLUDE_DIR}")
- MARK_AS_ADVANCED(DJBDNS_INCLUDE_DIRS DJBDNS_LIBRARIES)
-ENDIF(DJBDNS_LIBRARIES AND DJBDNS_INCLUDE_DIRS)
diff --git a/cmake/FindVala.cmake b/cmake/FindVala.cmake
deleted file mode 100644
index dc97dcd..0000000
--- a/cmake/FindVala.cmake
+++ /dev/null
@@ -1,70 +0,0 @@
-##
-# Find module for the Vala compiler (valac)
-#
-# This module determines wheter a Vala compiler is installed on the current
-# system and where its executable is.
-#
-# Call the module using "find_package(Vala) from within your CMakeLists.txt.
-#
-# The following variables will be set after an invocation:
-#
-# VALA_FOUND Whether the vala compiler has been found or not
-# VALA_EXECUTABLE Full path to the valac executable if it has been found
-# VALA_VERSION Version number of the available valac
-# VALA_USE_FILE Include this file to define the vala_precompile function
-##
-
-##
-# Copyright 2009-2010 Jakob Westhoff. All rights reserved.
-# Copyright 2010-2011 Daniel Pfeifer
-#
-# 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 JAKOB WESTHOFF ``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 JAKOB WESTHOFF OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
-# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
-# PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
-# LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
-# OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
-# ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-#
-# The views and conclusions contained in the software and documentation are those
-# of the authors and should not be interpreted as representing official policies,
-# either expressed or implied, of Jakob Westhoff
-##
-
-# Search for the valac executable in the usual system paths
-# Some distributions rename the valac to contain the major.minor in the binary name
-find_program(VALA_EXECUTABLE NAMES valac valac-0.24 valac-0.22 valac-0.20 valac-0.18 valac-0.16 valac-0.14 valac 0.12 valac 0.10)
-mark_as_advanced(VALA_EXECUTABLE)
-
-# Determine the valac version
-if(VALA_EXECUTABLE)
- execute_process(COMMAND ${VALA_EXECUTABLE} "--version"
- OUTPUT_VARIABLE VALA_VERSION
- OUTPUT_STRIP_TRAILING_WHITESPACE)
- string(REPLACE "Vala " "" VALA_VERSION "${VALA_VERSION}")
-endif(VALA_EXECUTABLE)
-
-# Handle the QUIETLY and REQUIRED arguments, which may be given to the find call.
-# Furthermore set VALA_FOUND to TRUE if Vala has been found (aka.
-# VALA_EXECUTABLE is set)
-
-include(FindPackageHandleStandardArgs)
-find_package_handle_standard_args(Vala
- REQUIRED_VARS VALA_EXECUTABLE
- VERSION_VAR VALA_VERSION)
-
-set(VALA_USE_FILE "${CMAKE_CURRENT_LIST_DIR}/UseVala.cmake")
-
diff --git a/cmake/GResource.cmake b/cmake/GResource.cmake
deleted file mode 100644
index eff49cc..0000000
--- a/cmake/GResource.cmake
+++ /dev/null
@@ -1,67 +0,0 @@
-#
-# Copyright (C) 2013 Venom authors and contributors
-#
-# This file is part of Venom.
-#
-# Venom is free software: you can redistribute it and/or modify
-# it under the terms of the GNU General Public License as published by
-# the Free Software Foundation, either version 3 of the License, or
-# (at your option) any later version.
-#
-# Venom is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with Venom. If not, see .
-#
-
-FIND_PROGRAM(GLIB_COMPILE_RESOURCES_EXECUTABLE NAMES glib-compile-resources)
-MARK_AS_ADVANCED(GLIB_COMPILE_RESOURCES_EXECUTABLE)
-
-INCLUDE(CMakeParseArguments)
-
-FUNCTION(GLIB_COMPILE_RESOURCES output)
- CMAKE_PARSE_ARGUMENTS(ARGS "" "SOURCE" ${ARGN})
- SET(DIRECTORY ${CMAKE_CURRENT_BINARY_DIR})
- SET(out_files "")
-
- FOREACH(src ${ARGS_SOURCE} ${ARGS_UNPARSED_ARGUMENTS})
- SET(in_file "${CMAKE_CURRENT_SOURCE_DIR}/${src}")
- GET_FILENAME_COMPONENT(WORKING_DIR ${in_file} PATH)
- STRING(REPLACE ".xml" ".c" src ${src})
- SET(out_file "${DIRECTORY}/${src}")
- GET_FILENAME_COMPONENT(OUPUT_DIR ${out_file} PATH)
- FILE(MAKE_DIRECTORY ${OUPUT_DIR})
- LIST(APPEND out_files "${DIRECTORY}/${src}")
-
- #FIXME implicit depends currently not working
- EXECUTE_PROCESS(
- COMMAND
- ${GLIB_COMPILE_RESOURCES_EXECUTABLE}
- "--generate-dependencies"
- ${in_file}
- WORKING_DIRECTORY ${WORKING_DIR}
- OUTPUT_VARIABLE in_file_dep
- )
- STRING(REGEX REPLACE "(\r?\n)" ";" in_file_dep "${in_file_dep}")
- SET(in_file_dep_path "")
- FOREACH(dep ${in_file_dep})
- LIST(APPEND in_file_dep_path "${WORKING_DIR}/${dep}")
- ENDFOREACH(dep ${in_file_dep})
- ADD_CUSTOM_COMMAND(
- OUTPUT ${out_file}
- WORKING_DIRECTORY ${WORKING_DIR}
- COMMAND
- ${GLIB_COMPILE_RESOURCES_EXECUTABLE}
- ARGS
- "--generate-source"
- "--target=${out_file}"
- ${in_file}
- DEPENDS
- ${in_file};${in_file_dep_path}
- )
- ENDFOREACH(src ${ARGS_SOURCES} ${ARGS_UNPARSED_ARGUMENTS})
- SET(${output} ${out_files} PARENT_SCOPE)
-ENDFUNCTION(GLIB_COMPILE_RESOURCES)
diff --git a/cmake/Gettext.cmake b/cmake/Gettext.cmake
deleted file mode 100644
index eff25a7..0000000
--- a/cmake/Gettext.cmake
+++ /dev/null
@@ -1,176 +0,0 @@
-# Gettext support: Create/Update pot file and
-#
-# To use: INCLUDE(Gettext)
-#
-# Most of the gettext support code is from FindGettext.cmake of cmake,
-# but it is included here because:
-#
-# 1. Some system like RHEL5 does not have FindGettext.cmake
-# 2. Bug of GETTEXT_CREATE_TRANSLATIONS make it unable to be include in 'All'
-# 3. It does not support xgettext
-#
-#===================================================================
-# Constants:
-# XGETTEXT_OPTIONS_DEFAULT: Default xgettext option:
-#===================================================================
-# Variables:
-# XGETTEXT_OPTIONS: Options pass to xgettext
-# Default: XGETTEXT_OPTIONS_DEFAULT
-# GETTEXT_MSGMERGE_EXECUTABLE: the full path to the msgmerge tool.
-# GETTEXT_MSGFMT_EXECUTABLE: the full path to the msgfmt tool.
-# GETTEXT_FOUND: True if gettext has been found.
-# XGETTEXT_EXECUTABLE: the full path to the xgettext.
-# XGETTEXT_FOUND: True if xgettext has been found.
-#
-#===================================================================
-# Macros:
-# GETTEXT_CREATE_POT(potFile
-# [OPTION xgettext_options]
-# SRC list_of_source_file_that_contains_msgid
-# )
-#
-# Generate .pot file.
-# OPTION xgettext_options: Override XGETTEXT_OPTIONS
-#
-# * Produced targets: pot_file
-#
-#-------------------------------------------------------------------
-# GETTEXT_CREATE_TRANSLATIONS ( outputFile [ALL] locale1 ... localeN
-# [COMMENT comment] )
-#
-# This will create a target "translations" which will convert the
-# given input po files into the binary output mo file. If the
-# ALL option is used, the translations will also be created when
-# building the default target.
-#
-# * Produced targets: translations
-#-------------------------------------------------------------------
-
-FIND_PROGRAM(GETTEXT_MSGMERGE_EXECUTABLE msgmerge)
-FIND_PROGRAM(GETTEXT_MSGFMT_EXECUTABLE msgfmt)
-FIND_PROGRAM(GETTEXT_MSGCAT_EXECUTABLE msgcat)
-FIND_PROGRAM(XGETTEXT_EXECUTABLE xgettext)
-
-SET(XGETTEXT_OPTIONS_DEFAULT
- --language=C --keyword=_ --keyword=N_ --keyword=C_:1c,2 --keyword=NC_:1c,2 -s
- --escape --add-comments="/" --package-name=${PROJECT_NAME} --package-version=${VERSION})
-
-IF (GETTEXT_MSGMERGE_EXECUTABLE AND GETTEXT_MSGFMT_EXECUTABLE AND GETTEXT_MSGCAT_EXECUTABLE)
- SET(GETTEXT_FOUND TRUE)
-ELSE (GETTEXT_MSGMERGE_EXECUTABLE AND GETTEXT_MSGFMT_EXECUTABLE)
- SET(GETTEXT_FOUND FALSE)
- IF (GetText_REQUIRED)
- MESSAGE(FATAL_ERROR "GetText not found")
- ENDIF (GetText_REQUIRED)
-ENDIF (GETTEXT_MSGMERGE_EXECUTABLE AND GETTEXT_MSGFMT_EXECUTABLE AND GETTEXT_MSGCAT_EXECUTABLE)
-
-IF(XGETTEXT_EXECUTABLE)
- SET(XGETTEXT_FOUND TRUE)
-ELSE(XGETTEXT_EXECUTABLE)
- MESSAGE(STATUS "xgettext not found.")
- SET(XGETTTEXT_FOUND FALSE)
-ENDIF(XGETTEXT_EXECUTABLE)
-
-IF(NOT DEFINED XGETTEXT_OPTIONS)
- SET(XGETTEXT_OPTIONS ${XGETTEXT_OPTIONS_DEFAULT})
-ENDIF(NOT DEFINED XGETTEXT_OPTIONS)
-
-IF(XGETTEXT_FOUND)
- MACRO(GETTEXT_CREATE_POT _potFile _pot_options )
- SET(_xgettext_options_list)
- SET(_src_list)
- SET(_src_list_abs)
- SET(_glade_list)
- SET(_glade_list_abs)
- SET(_stage "SRC")
- FOREACH(_pot_option ${_pot_options} ${ARGN})
- IF(_pot_option STREQUAL "OPTION")
- SET(_stage "OPTION")
- ELSEIF(_pot_option STREQUAL "SRC")
- SET(_stage "SRC")
- ELSEIF(_pot_option STREQUAL "GLADE")
- SET(_stage "GLADE")
- ELSE(_pot_option STREQUAL "OPTION")
- IF(_stage STREQUAL "OPTION")
- SET(_xgettext_options_list ${_xgettext_options_list} ${_pot_option})
- ELSEIF(_stage STREQUAL "GLADE")
- FILE(RELATIVE_PATH _relFile ${CMAKE_CURRENT_BINARY_DIR} ${CMAKE_SOURCE_DIR}/${_pot_option})
- GET_FILENAME_COMPONENT(_absFile ${_pot_option} ABSOLUTE)
- SET(_glade_list ${_glade_list} ${_relFile})
- SET(_glade_list_abs ${_glade_list_abs} ${_absFile})
- ELSEIF(_stage STREQUAL "SRC")
- FILE(RELATIVE_PATH _relFile ${CMAKE_CURRENT_BINARY_DIR} ${CMAKE_CURRENT_SOURCE_DIR}/${_pot_option})
- GET_FILENAME_COMPONENT(_absFile ${_pot_option} ABSOLUTE)
- SET(_src_list ${_src_list} ${_relFile})
- SET(_src_list_abs ${_src_list_abs} ${_absFile})
- ENDIF(_stage STREQUAL "OPTION")
- ENDIF(_pot_option STREQUAL "OPTION")
- ENDFOREACH(_pot_option ${_pot_options} ${ARGN})
-
- IF (_xgettext_options_list)
- SET(_xgettext_options ${_xgettext_options_list})
- ELSE(_xgettext_options_list)
- SET(_xgettext_options ${XGETTEXT_OPTIONS})
- ENDIF(_xgettext_options_list)
-
- #MESSAGE("${XGETTEXT_EXECUTABLE} ${_xgettext_options_list} -o ${_potFile} ${_src_list}")
- ADD_CUSTOM_COMMAND(OUTPUT pot_file
- COMMAND ${XGETTEXT_EXECUTABLE} ${_xgettext_options} -o ${_potFile} ${_src_list}
- DEPENDS ${_src_list_abs} ${GLADE_FILES}
- WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}
- )
-
- ADD_CUSTOM_TARGET(pot_file
- COMMAND ${XGETTEXT_EXECUTABLE} ${_xgettext_options_list} -o _source.pot ${_src_list}
- COMMAND ${XGETTEXT_EXECUTABLE} --language=Glade --omit-header -o _glade.pot ${_glade_list}
- COMMAND ${GETTEXT_MSGCAT_EXECUTABLE} -o ${_potFile} --use-first _source.pot _glade.pot
- DEPENDS ${_src_list_abs}
- WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}
- COMMENT "Extract translatable messages to ${_potFile}"
- )
- ENDMACRO(GETTEXT_CREATE_POT _potFile _pot_options)
-
-
- MACRO(GETTEXT_CREATE_TRANSLATIONS _potFile _firstLang)
- SET(_gmoFiles)
- GET_FILENAME_COMPONENT(_potBasename ${_potFile} NAME_WE)
- GET_FILENAME_COMPONENT(_absPotFile ${_potFile} ABSOLUTE)
-
- SET(_addToAll)
- SET(_is_comment FALSE)
-
- FOREACH (_currentLang ${_firstLang} ${ARGN})
- IF(_currentLang STREQUAL "ALL")
- SET(_addToAll "ALL")
- ELSEIF(_currentLang STREQUAL "COMMENT")
- SET(_is_comment TRUE)
- ELSEIF(_is_comment)
- SET(_is_comment FALSE)
- SET(_comment ${_currentLang})
- ELSE()
- SET(_lang ${_currentLang})
- GET_FILENAME_COMPONENT(_absFile ${_currentLang}.po ABSOLUTE)
- GET_FILENAME_COMPONENT(_abs_PATH ${_absFile} PATH)
- SET(_gmoFile ${CMAKE_CURRENT_BINARY_DIR}/${_lang}.mo)
-
- #MESSAGE("_absFile=${_absFile} _abs_PATH=${_abs_PATH} _lang=${_lang} curr_bin=${CMAKE_CURRENT_BINARY_DIR}")
- ADD_CUSTOM_COMMAND(
- OUTPUT ${_gmoFile}
- COMMAND ${GETTEXT_MSGMERGE_EXECUTABLE} --quiet --update --backup=none -s ${_absFile} ${_absPotFile}
- COMMAND ${GETTEXT_MSGFMT_EXECUTABLE} -o ${_gmoFile} ${_absFile}
- DEPENDS ${_absPotFile} ${_absFile}
- WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}
- )
-
- INSTALL(FILES ${_gmoFile} DESTINATION share/locale/${_lang}/LC_MESSAGES RENAME ${_potBasename}.mo)
- SET(_gmoFiles ${_gmoFiles} ${_gmoFile})
- ENDIF()
- ENDFOREACH (_currentLang )
-
- IF(DEFINED _comment)
- ADD_CUSTOM_TARGET(translations ${_addToAll} DEPENDS ${_gmoFiles} COMMENT ${_comment})
- ELSE(DEFINED _comment)
- ADD_CUSTOM_TARGET(translations ${_addToAll} DEPENDS ${_gmoFiles})
- ENDIF(DEFINED _comment)
- ENDMACRO(GETTEXT_CREATE_TRANSLATIONS )
-ENDIF(XGETTEXT_FOUND)
diff --git a/cmake/PkgCheckModulesFullpath.cmake b/cmake/PkgCheckModulesFullpath.cmake
deleted file mode 100644
index d3ac4a3..0000000
--- a/cmake/PkgCheckModulesFullpath.cmake
+++ /dev/null
@@ -1,71 +0,0 @@
-#
-# Copyright (C) 2013 Venom authors and contributors
-#
-# This file is part of Venom.
-#
-# Venom is free software: you can redistribute it and/or modify
-# it under the terms of the GNU General Public License as published by
-# the Free Software Foundation, either version 3 of the License, or
-# (at your option) any later version.
-#
-# Venom is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with Venom. If not, see .
-#
-
-MACRO(PKG_CHECK_MODULES_FULLPATH MODULE_PREFIX)
- PKG_CHECK_MODULES(${MODULE_PREFIX} ${ARGN})
- IF( BUILD_STATIC_EXECUTABLES )
- SET(LINK_${MODULE_PREFIX}_STATIC TRUE)
- UNSET(LINK_${MODULE_PREFIX}_STATIC CACHE)
- ELSE( BUILD_STATIC_EXECUTABLES )
- OPTION(LINK_${MODULE_PREFIX}_STATIC "Link module ${MODULE_PREFIX} static" FALSE)
- ENDIF( BUILD_STATIC_EXECUTABLES )
- IF( LINK_${MODULE_PREFIX}_STATIC )
- MESSAGE("Linking module ${MODULE_PREFIX} statically.")
- SET(CMAKE_FIND_LIBRARY_SUFFIXES_BAK ${CMAKE_FIND_LIBRARY_SUFFIXES})
- SET(CMAKE_FIND_LIBRARY_SUFFIXES .a)
- FOREACH(i ${${MODULE_PREFIX}_STATIC_LIBRARIES})
- FIND_LIBRARY( ${i}_LIBRARY
- NAMES ${i}
- PATHS ${${MODULE_PREFIX}_LIBRARY_DIRS}
- )
- IF( ${${i}_LIBRARY} MATCHES ${i}_LIBRARY-NOTFOUND)
- MESSAGE("Static library file \"${i}.a\" needed for linking module ${MODULE_PREFIX} not found!")
- ELSE()
- LIST( APPEND ${MODULE_PREFIX}_STATIC_LIBRARIES_FULLPATH ${${i}_LIBRARY} )
- ENDIF()
- UNSET(${i}_LIBRARY CACHE)
- ENDFOREACH(i)
- SET( ${MODULE_PREFIX}_LIBRARIES ${${MODULE_PREFIX}_STATIC_LIBRARIES_FULLPATH} )
- SET(CMAKE_FIND_LIBRARY_SUFFIXES ${CMAKE_FIND_LIBRARY_SUFFIXES_BAK})
- SET(CMAKE_FIND_LIBRARY_SUFFIXES_BAK)
- SET( ${MODULE_PREFIX}_CFLAGS ${${MODULE_PREFIX}_STATIC_CFLAGS} )
- SET( ${MODULE_PREFIX}_CFLAGS_OTHER ${${MODULE_PREFIX}_STATIC_CFLAGS_OTHER} )
- MESSAGE("${${MODULE_PREFIX}_LIBRARIES}")
- ELSE()
- FOREACH(i ${${MODULE_PREFIX}_LIBRARIES})
- SET(${i}_LIBRARY ${i}_LIBRARY-NOTFOUND)
- FIND_LIBRARY( ${i}_LIBRARY
- NAMES ${i}
- PATHS ${${MODULE_PREFIX}_LIBRARY_DIRS}
- )
- IF( ${${i}_LIBRARY} MATCHES ${i}_LIBRARY-NOTFOUND)
- MESSAGE( "Library \"${i}\" not found!" )
- ELSE()
- LIST( APPEND ${MODULE_PREFIX}_LIBRARIES_FULLPATH ${${i}_LIBRARY} )
- ENDIF()
- UNSET(${i}_LIBRARY CACHE)
- ENDFOREACH(i)
- SET( ${MODULE_PREFIX}_LIBRARIES ${${MODULE_PREFIX}_LIBRARIES_FULLPATH} )
- ENDIF()
- IF(${MODULE_PREFIX}_VERSION)
- STRING(REGEX REPLACE "^([^ .]+)\\.[^ .]+\\.[^ .]+$" "\\1" ${MODULE_PREFIX}_VERSION_MAJOR ${${MODULE_PREFIX}_VERSION})
- STRING(REGEX REPLACE "^[^ .]+\\.([^ .]+)\\.[^ .]+$" "\\1" ${MODULE_PREFIX}_VERSION_MINOR ${${MODULE_PREFIX}_VERSION})
- STRING(REGEX REPLACE "^[^ .]+\\.[^ .]+\\.([^ .]+)$" "\\1" ${MODULE_PREFIX}_VERSION_PATCH ${${MODULE_PREFIX}_VERSION})
- ENDIF(${MODULE_PREFIX}_VERSION)
-ENDMACRO(PKG_CHECK_MODULES_FULLPATH)
diff --git a/cmake/Rsvg.cmake b/cmake/Rsvg.cmake
deleted file mode 100644
index 459a7a2..0000000
--- a/cmake/Rsvg.cmake
+++ /dev/null
@@ -1,72 +0,0 @@
-#
-# Copyright (C) 2013 Venom authors and contributors
-#
-# This file is part of Venom.
-#
-# Venom is free software: you can redistribute it and/or modify
-# it under the terms of the GNU General Public License as published by
-# the Free Software Foundation, either version 3 of the License, or
-# (at your option) any later version.
-#
-# Venom is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with Venom. If not, see .
-#
-FIND_PROGRAM(RSVG_CONVERT_EXECUTABLE NAMES rsvg-convert)
-MARK_AS_ADVANCED(RSVG_CONVERT_EXECUTABLE)
-
-INCLUDE(CMakeParseArguments)
-
-FUNCTION(RSVG_CONVERT output)
- CMAKE_PARSE_ARGUMENTS(ARGS "" "DESTINATION;FORMAT;SIZE;SOURCE" ${ARGN})
- IF(ARGS_DESTINATION)
- SET(DESTINATION ${ARGS_DESTINATION})
- ELSE(ARGS_DESTINATION)
- SET(DESTINATION ${CMAKE_CURRENT_SOURCE_DIR})
- ENDIF(ARGS_DESTINATION)
- IF(ARGS_FORMAT)
- SET(FORMAT ${ARGS_FORMAT})
- ELSE(ARGS_FORMAT)
- SET(FORMAT "png")
- ENDIF(ARGS_FORMAT)
- IF(ARGS_SIZE)
- SET(SIZE ${ARGS_SIZE})
- ELSE(ARGS_SIZE)
- SET(SIZE "16" "32" "48" "64" "128" "256")
- ENDIF(ARGS_SIZE)
-
- SET(out_files "")
-
- FOREACH(current_size ${SIZE})
- SET(CURRENT_DESTINATION ${DESTINATION}/${current_size}x${current_size})
- FILE(MAKE_DIRECTORY ${CURRENT_DESTINATION})
- FOREACH(src ${ARGS_SOURCE} ${ARGS_UNPARSED_ARGUMENTS})
- SET(in_file "${CMAKE_CURRENT_SOURCE_DIR}/${src}")
- GET_FILENAME_COMPONENT(WORKING_DIR ${in_file} PATH)
- STRING(REPLACE ".svg" ".${FORMAT}" src ${src})
- GET_FILENAME_COMPONENT(FILENAME ${src} NAME)
- SET(out_file "${CURRENT_DESTINATION}/${FILENAME}")
- LIST(APPEND out_files ${out_file})
-
- ADD_CUSTOM_COMMAND(
- WORKING_DIRECTORY ${WORKING_DIR}
- OUTPUT ${out_file}
- COMMAND
- ${RSVG_CONVERT_EXECUTABLE}
- ARGS
- ${in_file}
- "-w" ${current_size}
- "-h" ${current_size}
- "-f" ${FORMAT}
- "-o" ${out_file}
- DEPENDS
- ${in_file}
- )
- ENDFOREACH(src ${ARGS_SOURCES} ${ARGS_UNPARSED_ARGUMENTS})
- ENDFOREACH(current_size ${ARGS_SIZE})
- SET(${output} ${out_files} PARENT_SCOPE)
-ENDFUNCTION(RSVG_CONVERT)
diff --git a/cmake/UseVala.cmake b/cmake/UseVala.cmake
deleted file mode 100644
index 352921c..0000000
--- a/cmake/UseVala.cmake
+++ /dev/null
@@ -1,180 +0,0 @@
-##
-# Compile vala files to their c equivalents for further processing.
-#
-# The "vala_precompile" function takes care of calling the valac executable on
-# the given source to produce c files which can then be processed further using
-# default cmake functions.
-#
-# The first parameter provided is a variable, which will be filled with a list
-# of c files outputted by the vala compiler. This list can than be used in
-# conjuction with functions like "add_executable" or others to create the
-# neccessary compile rules with CMake.
-#
-# The following sections may be specified afterwards to provide certain options
-# to the vala compiler:
-#
-# SOURCES
-# A list of .vala files to be compiled. Please take care to add every vala
-# file belonging to the currently compiled project or library as Vala will
-# otherwise not be able to resolve all dependencies.
-#
-# PACKAGES
-# A list of vala packages/libraries to be used during the compile cycle. The
-# package names are exactly the same, as they would be passed to the valac
-# "--pkg=" option.
-#
-# OPTIONS
-# A list of optional options to be passed to the valac executable. This can be
-# used to pass "--thread" for example to enable multi-threading support.
-#
-# CUSTOM_VAPIS
-# A list of custom vapi files to be included for compilation. This can be
-# useful to include freshly created vala libraries without having to install
-# them in the system.
-#
-# GENERATE_VAPI
-# Pass all the needed flags to the compiler to create an internal vapi for
-# the compiled library. The provided name will be used for this and a
-# .vapi file will be created.
-#
-# GENERATE_HEADER
-# Let the compiler generate a header file for the compiled code. There will
-# be a header file as well as an internal header file being generated called
-# .h and _internal.h
-#
-# The following call is a simple example to the vala_precompile macro showing
-# an example to every of the optional sections:
-#
-# find_package(Vala "0.12" REQUIRED)
-# inlcude(${VALA_USE_FILE})
-#
-# vala_precompile(VALA_C
-# SOURCES
-# source1.vala
-# source2.vala
-# source3.vala
-# PACKAGES
-# gtk+-2.0
-# gio-1.0
-# posix
-# DIRECTORY
-# gen
-# OPTIONS
-# --thread
-# CUSTOM_VAPIS
-# some_vapi.vapi
-# GENERATE_VAPI
-# myvapi
-# GENERATE_HEADER
-# myheader
-# )
-#
-# Most important is the variable VALA_C which will contain all the generated c
-# file names after the call.
-##
-
-##
-# Copyright 2009-2010 Jakob Westhoff. All rights reserved.
-# Copyright 2010-2011 Daniel Pfeifer
-#
-# 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 JAKOB WESTHOFF ``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 JAKOB WESTHOFF OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
-# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
-# PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
-# LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
-# OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
-# ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-#
-# The views and conclusions contained in the software and documentation are those
-# of the authors and should not be interpreted as representing official policies,
-# either expressed or implied, of Jakob Westhoff
-##
-
-include(CMakeParseArguments)
-
-function(vala_precompile output)
- cmake_parse_arguments(ARGS "" "DIRECTORY;GENERATE_HEADER;GENERATE_VAPI"
- "SOURCES;PACKAGES;OPTIONS;CUSTOM_VAPIS" ${ARGN})
-
- if(ARGS_DIRECTORY)
- set(DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/${ARGS_DIRECTORY})
- else(ARGS_DIRECTORY)
- set(DIRECTORY ${CMAKE_CURRENT_BINARY_DIR})
- endif(ARGS_DIRECTORY)
- include_directories(${DIRECTORY})
- set(vala_pkg_opts "")
- foreach(pkg ${ARGS_PACKAGES})
- list(APPEND vala_pkg_opts "--pkg=${pkg}")
- endforeach(pkg ${ARGS_PACKAGES})
- set(in_files "")
- set(out_files "")
- foreach(src ${ARGS_SOURCES} ${ARGS_UNPARSED_ARGUMENTS})
- list(APPEND in_files "${CMAKE_CURRENT_SOURCE_DIR}/${src}")
- string(REPLACE ".vala" ".c" src ${src})
- string(REPLACE ".gs" ".c" src ${src})
- set(out_file "${DIRECTORY}/${src}")
- list(APPEND out_files "${DIRECTORY}/${src}")
- endforeach(src ${ARGS_SOURCES} ${ARGS_UNPARSED_ARGUMENTS})
-
- set(custom_vapi_arguments "")
- if(ARGS_CUSTOM_VAPIS)
- foreach(vapi ${ARGS_CUSTOM_VAPIS})
- if(${vapi} MATCHES ${CMAKE_SOURCE_DIR} OR ${vapi} MATCHES ${CMAKE_BINARY_DIR})
- list(APPEND custom_vapi_arguments ${vapi})
- else (${vapi} MATCHES ${CMAKE_SOURCE_DIR} OR ${vapi} MATCHES ${CMAKE_BINARY_DIR})
- list(APPEND custom_vapi_arguments ${CMAKE_CURRENT_SOURCE_DIR}/${vapi})
- endif(${vapi} MATCHES ${CMAKE_SOURCE_DIR} OR ${vapi} MATCHES ${CMAKE_BINARY_DIR})
- endforeach(vapi ${ARGS_CUSTOM_VAPIS})
- endif(ARGS_CUSTOM_VAPIS)
-
- set(vapi_arguments "")
- if(ARGS_GENERATE_VAPI)
- list(APPEND out_files "${DIRECTORY}/${ARGS_GENERATE_VAPI}.vapi")
- set(vapi_arguments "--internal-vapi=${ARGS_GENERATE_VAPI}.vapi")
-
- # Header and internal header is needed to generate internal vapi
- if (NOT ARGS_GENERATE_HEADER)
- set(ARGS_GENERATE_HEADER ${ARGS_GENERATE_VAPI})
- endif(NOT ARGS_GENERATE_HEADER)
- endif(ARGS_GENERATE_VAPI)
-
- set(header_arguments "")
- if(ARGS_GENERATE_HEADER)
- list(APPEND out_files "${DIRECTORY}/${ARGS_GENERATE_HEADER}.h")
- list(APPEND out_files "${DIRECTORY}/${ARGS_GENERATE_HEADER}_internal.h")
- list(APPEND header_arguments "--header=${DIRECTORY}/${ARGS_GENERATE_HEADER}.h")
- list(APPEND header_arguments "--internal-header=${DIRECTORY}/${ARGS_GENERATE_HEADER}_internal.h")
- endif(ARGS_GENERATE_HEADER)
-
- add_custom_command(OUTPUT ${out_files}
- COMMAND
- ${VALA_EXECUTABLE}
- ARGS
- "-C"
- ${header_arguments}
- ${vapi_arguments}
- "-b" ${CMAKE_CURRENT_SOURCE_DIR}
- "-d" ${DIRECTORY}
- ${vala_pkg_opts}
- ${ARGS_OPTIONS}
- ${in_files}
- ${custom_vapi_arguments}
- DEPENDS
- ${in_files}
- ${ARGS_CUSTOM_VAPIS}
- )
- set(${output} ${out_files} PARENT_SCOPE)
-endfunction(vala_precompile)
diff --git a/cmake/mingw-toolchain.cmake b/cmake/mingw-toolchain.cmake
deleted file mode 100644
index 027cbcb..0000000
--- a/cmake/mingw-toolchain.cmake
+++ /dev/null
@@ -1,35 +0,0 @@
-# the name of the target operating system
-SET(CMAKE_SYSTEM_NAME Windows)
-
-# Choose an appropriate compiler prefix
-
-# for classical mingw32
-# see http://www.mingw.org/
-#set(COMPILER_PREFIX "i586-mingw32msvc")
-
-# for 32 or 64 bits mingw-w64
-# see http://mingw-w64.sourceforge.net/
-#set(COMPILER_PREFIX "i686-w64-mingw32")
-#set(COMPILER_PREFIX "x86_64-w64-mingw32"
-
-set(COMPILER_PREFIX "i486-mingw32")
-
-# which compilers to use for C and C++
-find_program(CMAKE_RC_COMPILER NAMES ${COMPILER_PREFIX}-windres)
-#SET(CMAKE_RC_COMPILER ${COMPILER_PREFIX}-windres)
-find_program(CMAKE_C_COMPILER NAMES ${COMPILER_PREFIX}-gcc)
-#SET(CMAKE_C_COMPILER ${COMPILER_PREFIX}-gcc)
-find_program(CMAKE_CXX_COMPILER NAMES ${COMPILER_PREFIX}-g++)
-#SET(CMAKE_CXX_COMPILER ${COMPILER_PREFIX}-g++)
-
-
-# here is the target environment located
-SET(CMAKE_FIND_ROOT_PATH /usr/${COMPILER_PREFIX})
-
-# adjust the default behaviour of the FIND_XXX() commands:
-# search headers and libraries in the target environment, search
-# programs in the host environment
-set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER)
-set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY)
-set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY)
-
diff --git a/configure.in b/configure.in
deleted file mode 100644
index 8aa4ab9..0000000
--- a/configure.in
+++ /dev/null
@@ -1 +0,0 @@
-# Dummy file to let valencia find the project root folder
diff --git a/data/chat.tox.venom.desktop.in b/data/chat.tox.venom.desktop.in
new file mode 100644
index 0000000..4c88f1e
--- /dev/null
+++ b/data/chat.tox.venom.desktop.in
@@ -0,0 +1,12 @@
+[Desktop Entry]
+Name=Venom
+Comment=A modern Tox client for the Linux desktop
+Keywords=tox;instant messaging;video chat;
+Exec=venom
+Icon=chat.tox.venom-symbolic
+Terminal=false
+Type=Application
+Categories=InstantMessaging;Network;
+DBusActivatable=true
+StartupNotify=true
+X-GNOME-UsesNotifications=true
diff --git a/data/chat.tox.venom.service.in b/data/chat.tox.venom.service.in
new file mode 100644
index 0000000..cb144ca
--- /dev/null
+++ b/data/chat.tox.venom.service.in
@@ -0,0 +1,3 @@
+[D-BUS Service]
+Name=chat.tox.venom
+Exec=@bindir@/venom --gapplication-service
diff --git a/data/icons/symbolic/chat.tox.venom-symbolic.svg b/data/icons/symbolic/chat.tox.venom-symbolic.svg
new file mode 100644
index 0000000..46b6996
--- /dev/null
+++ b/data/icons/symbolic/chat.tox.venom-symbolic.svg
@@ -0,0 +1,11 @@
+
+
diff --git a/data/meson.build b/data/meson.build
new file mode 100644
index 0000000..1fea8fd
--- /dev/null
+++ b/data/meson.build
@@ -0,0 +1,23 @@
+i18n.merge_file(
+ input: 'chat.tox.venom.desktop.in',
+ output: 'chat.tox.venom.desktop',
+ type: 'desktop',
+ po_dir: '../po',
+ install: true,
+ install_dir: join_paths(get_option('datadir'), 'applications')
+)
+
+service_conf = configuration_data()
+service_conf.set('bindir', join_paths(get_option('prefix'), get_option('bindir')))
+configure_file(
+ input: 'chat.tox.venom.service.in',
+ output: 'chat.tox.venom.service',
+ configuration: service_conf,
+ install: true,
+ install_dir: join_paths(get_option('datadir'), 'dbus-1', 'services')
+)
+
+install_data(
+ 'icons/symbolic/chat.tox.venom-symbolic.svg',
+ install_dir: join_paths(get_option('datadir'), 'icons', 'hicolor', 'symbolic', 'apps'),
+)
diff --git a/icons/128x128/venom.png b/icons/128x128/venom.png
deleted file mode 100644
index 115c35e..0000000
Binary files a/icons/128x128/venom.png and /dev/null differ
diff --git a/icons/16x16/venom.png b/icons/16x16/venom.png
deleted file mode 100644
index ef11b71..0000000
Binary files a/icons/16x16/venom.png and /dev/null differ
diff --git a/icons/256x256/venom.png b/icons/256x256/venom.png
deleted file mode 100644
index 42c02d4..0000000
Binary files a/icons/256x256/venom.png and /dev/null differ
diff --git a/icons/32x32/venom.png b/icons/32x32/venom.png
deleted file mode 100644
index 2ab9664..0000000
Binary files a/icons/32x32/venom.png and /dev/null differ
diff --git a/icons/48x48/venom.png b/icons/48x48/venom.png
deleted file mode 100644
index 3db8784..0000000
Binary files a/icons/48x48/venom.png and /dev/null differ
diff --git a/icons/64x64/venom.png b/icons/64x64/venom.png
deleted file mode 100644
index bba6fe9..0000000
Binary files a/icons/64x64/venom.png and /dev/null differ
diff --git a/icons/CMakeLists.txt b/icons/CMakeLists.txt
deleted file mode 100644
index 7ca81db..0000000
--- a/icons/CMakeLists.txt
+++ /dev/null
@@ -1,59 +0,0 @@
-#
-# Copyright (C) 2013 Venom authors and contributors
-#
-# This file is part of Venom.
-#
-# Venom is free software: you can redistribute it and/or modify
-# it under the terms of the GNU General Public License as published by
-# the Free Software Foundation, either version 3 of the License, or
-# (at your option) any later version.
-#
-# Venom is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with Venom. If not, see .
-#
-
-INCLUDE(Rsvg OPTIONAL)
-
-SET(PIXMAP_SIZES
- 16
- 32
- 48
- 64
- 128
- 256
-)
-
-SET( VENOM_SVG
- scalable/venom.svg
-)
-
-IF(RSVG_CONVERT_EXECUTABLE AND GENERATE_PIXMAPS)
- RSVG_CONVERT( VENOM_GENERATED_PIXMAPS
- SOURCE
- ${VENOM_SVG}
- )
- ADD_CUSTOM_TARGET( generate_pixmaps
- ALL
- COMMENT
- "Generating pixmaps from svg"
- DEPENDS
- ${VENOM_GENERATED_PIXMAPS}
- )
-ENDIF(RSVG_CONVERT_EXECUTABLE AND GENERATE_PIXMAPS)
-
-FOREACH(pixmap_size ${PIXMAP_SIZES})
- INSTALL(FILES ${pixmap_size}x${pixmap_size}/venom.png
- DESTINATION
- "${COMMON_DATA_DIR}/icons/hicolor/${pixmap_size}x${pixmap_size}/apps"
- )
-ENDFOREACH(pixmap_size ${PIXMAP_SIZES})
-
-INSTALL(FILES ${VENOM_SVG}
- DESTINATION "${COMMON_DATA_DIR}/icons/hicolor/scalable/apps")
-INSTALL(FILES 256x256/venom.png
- DESTINATION "${COMMON_DATA_DIR}/pixmaps")
diff --git a/icons/scalable/venom.svg b/icons/scalable/venom.svg
deleted file mode 100644
index f286350..0000000
--- a/icons/scalable/venom.svg
+++ /dev/null
@@ -1,4 +0,0 @@
-
diff --git a/icons/scalable/venom_faenza.svg b/icons/scalable/venom_faenza.svg
deleted file mode 100644
index 1530b46..0000000
--- a/icons/scalable/venom_faenza.svg
+++ /dev/null
@@ -1,57 +0,0 @@
-
diff --git a/icons/scalable/venom_numix.svg b/icons/scalable/venom_numix.svg
deleted file mode 100644
index 4379d24..0000000
--- a/icons/scalable/venom_numix.svg
+++ /dev/null
@@ -1,24 +0,0 @@
-
diff --git a/meson.build b/meson.build
new file mode 100644
index 0000000..b2b2c35
--- /dev/null
+++ b/meson.build
@@ -0,0 +1,27 @@
+project('venom', ['vala', 'c'],
+ license: 'GPL3+',
+ version: '0.3.0'
+)
+
+i18n = import('i18n')
+gnome = import('gnome')
+valac = meson.get_compiler('vala')
+
+localedir = join_paths(get_option('prefix'), get_option('localedir'))
+
+conf_data = configuration_data()
+conf_data.set_quoted('VENOM_VERSION', meson.project_version())
+conf_data.set_quoted('GETTEXT_PACKAGE', meson.project_name())
+conf_data.set_quoted('GETTEXT_PATH', localedir)
+
+subdir('scripts')
+subdir('data')
+subdir('po')
+subdir('src')
+subdir('src/testing')
+
+message('\n'.join(['',
+' @0@-@1@'.format(meson.project_name(), meson.project_version()),
+' prefix: @0@'.format(get_option('prefix')),
+' buildtype: @0@'.format(get_option('buildtype'))
+]))
diff --git a/misc/CMakeLists.txt b/misc/CMakeLists.txt
deleted file mode 100644
index d495062..0000000
--- a/misc/CMakeLists.txt
+++ /dev/null
@@ -1,37 +0,0 @@
-#
-# Copyright (C) 2013 Venom authors and contributors
-#
-# This file is part of Venom.
-#
-# Venom is free software: you can redistribute it and/or modify
-# it under the terms of the GNU General Public License as published by
-# the Free Software Foundation, either version 3 of the License, or
-# (at your option) any later version.
-#
-# Venom is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with Venom. If not, see .
-#
-
-
-
-IF(WIN32)
- CONFIGURE_FILE (venom.rc.in venom.rc)
- CONFIGURE_FILE (venom.ico venom.ico COPYONLY)
- SET(VENOM_RESOURCE_FILE ${CMAKE_CURRENT_BINARY_DIR}/venom.rc PARENT_SCOPE)
-ELSE(WIN32)
- CONFIGURE_FILE (venom.desktop.in venom.desktop)
- INSTALL(
- FILES
- ${CMAKE_CURRENT_BINARY_DIR}/venom.desktop
- DESTINATION
- ${COMMON_DATA_DIR}/applications
- )
-ENDIF(WIN32)
-
-
-
diff --git a/misc/clearwhitespace.sh b/misc/clearwhitespace.sh
deleted file mode 100755
index 26ac32f..0000000
--- a/misc/clearwhitespace.sh
+++ /dev/null
@@ -1,4 +0,0 @@
-#!/bin/sh
-for i in $*; do
- sed 's/\s\+$//g' -i $i
-done
diff --git a/misc/create_ico.sh b/misc/create_ico.sh
deleted file mode 100755
index 5095ddc..0000000
--- a/misc/create_ico.sh
+++ /dev/null
@@ -1,47 +0,0 @@
-#!/bin/sh
-#
-# Copyright (C) 2013 Venom authors and contributors
-#
-# This file is part of Venom.
-#
-# Venom is free software: you can redistribute it and/or modify
-# it under the terms of the GNU General Public License as published by
-# the Free Software Foundation, either version 3 of the License, or
-# (at your option) any later version.
-#
-# Venom is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with Venom. If not, see .
-#
-
-venom_svg="../icons/scalable/venom.svg"
-
-rsvg-convert $venom_svg -w 256 -h 256 -o venom_256.png
-rsvg-convert $venom_svg -w 48 -h 48 -o venom_48.png
-rsvg-convert $venom_svg -w 32 -h 32 -o venom_32.png
-rsvg-convert $venom_svg -w 16 -h 16 -o venom_16.png
-
-convert venom_48.png -colors 256 -depth 8 venom_48_8.png
-convert venom_32.png -colors 256 -depth 8 venom_32_8.png
-convert venom_16.png -colors 256 -depth 8 venom_16_8.png
-
-convert venom_48.png -colors 16 -depth 4 venom_48_4.png
-convert venom_32.png -colors 16 -depth 4 venom_32_4.png
-convert venom_16.png -colors 16 -depth 4 venom_16_4.png
-
-convert venom_256.png \
- venom_48.png \
- venom_32.png \
- venom_16.png \
- venom_48_8.png \
- venom_32_8.png \
- venom_16_8.png \
- venom_48_4.png \
- venom_32_4.png \
- venom_16_4.png \
- venom.ico
-rm venom_*.png
diff --git a/misc/pkgdesc.txt b/misc/pkgdesc.txt
deleted file mode 100644
index bd19ae3..0000000
--- a/misc/pkgdesc.txt
+++ /dev/null
@@ -1 +0,0 @@
-Venom is a graphical user interface for Project-Tox.
diff --git a/misc/svg/button_icons/arrow_medgrey.svg b/misc/svg/button_icons/arrow_medgrey.svg
deleted file mode 100644
index ab4e1cc..0000000
--- a/misc/svg/button_icons/arrow_medgrey.svg
+++ /dev/null
@@ -1,7 +0,0 @@
-
-
-
-
diff --git a/misc/svg/button_icons/arrow_white.svg b/misc/svg/button_icons/arrow_white.svg
deleted file mode 100644
index ba9df6a..0000000
--- a/misc/svg/button_icons/arrow_white.svg
+++ /dev/null
@@ -1,7 +0,0 @@
-
-
-
-
diff --git a/misc/svg/button_icons/attach.svg b/misc/svg/button_icons/attach.svg
deleted file mode 100644
index 352cd93..0000000
--- a/misc/svg/button_icons/attach.svg
+++ /dev/null
@@ -1,18 +0,0 @@
-
-
-
diff --git a/misc/svg/button_icons/call.svg b/misc/svg/button_icons/call.svg
deleted file mode 100644
index 1541a7a..0000000
--- a/misc/svg/button_icons/call.svg
+++ /dev/null
@@ -1,15 +0,0 @@
-
-
-
diff --git a/misc/svg/button_icons/check.svg b/misc/svg/button_icons/check.svg
deleted file mode 100644
index 6023175..0000000
--- a/misc/svg/button_icons/check.svg
+++ /dev/null
@@ -1,15 +0,0 @@
-
-
-
diff --git a/misc/svg/button_icons/emoticon.svg b/misc/svg/button_icons/emoticon.svg
deleted file mode 100644
index 7c124cb..0000000
--- a/misc/svg/button_icons/emoticon.svg
+++ /dev/null
@@ -1,15 +0,0 @@
-
-
-
diff --git a/misc/svg/button_icons/no.svg b/misc/svg/button_icons/no.svg
deleted file mode 100644
index 8a77189..0000000
--- a/misc/svg/button_icons/no.svg
+++ /dev/null
@@ -1,15 +0,0 @@
-
-
-
diff --git a/misc/svg/button_icons/pause.svg b/misc/svg/button_icons/pause.svg
deleted file mode 100644
index 8d13c39..0000000
--- a/misc/svg/button_icons/pause.svg
+++ /dev/null
@@ -1,10 +0,0 @@
-
-
-
-
diff --git a/misc/svg/button_icons/sendmessage.svg b/misc/svg/button_icons/sendmessage.svg
deleted file mode 100644
index 41c73fb..0000000
--- a/misc/svg/button_icons/sendmessage.svg
+++ /dev/null
@@ -1,15 +0,0 @@
-
-
-
diff --git a/misc/svg/button_icons/video.svg b/misc/svg/button_icons/video.svg
deleted file mode 100644
index 5e871de..0000000
--- a/misc/svg/button_icons/video.svg
+++ /dev/null
@@ -1,18 +0,0 @@
-
-
-
diff --git a/misc/svg/clean.sh b/misc/svg/clean.sh
deleted file mode 100755
index a2b88d3..0000000
--- a/misc/svg/clean.sh
+++ /dev/null
@@ -1,24 +0,0 @@
-#!/bin/bash
-# Copyright (C) 2013 Venom authors and contributors
-#
-# This file is part of Venom.
-#
-# Venom is free software: you can redistribute it and/or modify
-# it under the terms of the GNU General Public License as published by
-# the Free Software Foundation, either version 3 of the License, or
-# (at your option) any later version.
-#
-# Venom is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with Venom. If not, see .
-#
-for i in $(find . -type f -name "*.svg");
-do
- echo "# cleaning $i"
- svgcleaner-cli "$i" "$i" --join-style-atts
-done
-# vim:set ts=2 sw=2 et:
diff --git a/misc/svg/contact_list_icons/add.svg b/misc/svg/contact_list_icons/add.svg
deleted file mode 100644
index dd973a0..0000000
--- a/misc/svg/contact_list_icons/add.svg
+++ /dev/null
@@ -1,7 +0,0 @@
-
diff --git a/misc/svg/contact_list_icons/group.svg b/misc/svg/contact_list_icons/group.svg
deleted file mode 100644
index 36a1a1c..0000000
--- a/misc/svg/contact_list_icons/group.svg
+++ /dev/null
@@ -1,22 +0,0 @@
-
-
-
diff --git a/misc/svg/contact_list_icons/settings.svg b/misc/svg/contact_list_icons/settings.svg
deleted file mode 100644
index a8f7360..0000000
--- a/misc/svg/contact_list_icons/settings.svg
+++ /dev/null
@@ -1,15 +0,0 @@
-
-
-
diff --git a/misc/svg/contact_list_icons/transfer.svg b/misc/svg/contact_list_icons/transfer.svg
deleted file mode 100644
index 0f867a0..0000000
--- a/misc/svg/contact_list_icons/transfer.svg
+++ /dev/null
@@ -1,18 +0,0 @@
-
-
-
diff --git a/misc/svg/render.sh b/misc/svg/render.sh
deleted file mode 100755
index 16fa192..0000000
--- a/misc/svg/render.sh
+++ /dev/null
@@ -1,25 +0,0 @@
-#!/bin/bash
-# Copyright (C) 2013 Venom authors and contributors
-#
-# This file is part of Venom.
-#
-# Venom is free software: you can redistribute it and/or modify
-# it under the terms of the GNU General Public License as published by
-# the Free Software Foundation, either version 3 of the License, or
-# (at your option) any later version.
-#
-# Venom is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with Venom. If not, see .
-#
-for i in $(find . -type f -name "*.svg");
-do
- cvtpath="../../src/pixmaps/${i%.*}.png"
- echo "# rendering $i to $cvtpath"
- rsvg-convert "$i" -o "$cvtpath"
-done
-# vim:set ts=2 sw=2 et:
diff --git a/misc/svg/status/dot_away.svg b/misc/svg/status/dot_away.svg
deleted file mode 100644
index 93a8e35..0000000
--- a/misc/svg/status/dot_away.svg
+++ /dev/null
@@ -1,4 +0,0 @@
-
diff --git a/misc/svg/status/dot_away_notification.svg b/misc/svg/status/dot_away_notification.svg
deleted file mode 100644
index 2e6d7d8..0000000
--- a/misc/svg/status/dot_away_notification.svg
+++ /dev/null
@@ -1,5 +0,0 @@
-
diff --git a/misc/svg/status/dot_busy.svg b/misc/svg/status/dot_busy.svg
deleted file mode 100644
index 6eed170..0000000
--- a/misc/svg/status/dot_busy.svg
+++ /dev/null
@@ -1,6 +0,0 @@
-
diff --git a/misc/svg/status/dot_busy_notification.svg b/misc/svg/status/dot_busy_notification.svg
deleted file mode 100644
index 8cb2a13..0000000
--- a/misc/svg/status/dot_busy_notification.svg
+++ /dev/null
@@ -1,7 +0,0 @@
-
diff --git a/misc/svg/status/dot_idle.svg b/misc/svg/status/dot_idle.svg
deleted file mode 100644
index b0155cb..0000000
--- a/misc/svg/status/dot_idle.svg
+++ /dev/null
@@ -1,4 +0,0 @@
-
diff --git a/misc/svg/status/dot_idle_notification.svg b/misc/svg/status/dot_idle_notification.svg
deleted file mode 100644
index 3e4e6cd..0000000
--- a/misc/svg/status/dot_idle_notification.svg
+++ /dev/null
@@ -1,5 +0,0 @@
-
diff --git a/misc/svg/status/dot_online.svg b/misc/svg/status/dot_online.svg
deleted file mode 100644
index a65693a..0000000
--- a/misc/svg/status/dot_online.svg
+++ /dev/null
@@ -1,6 +0,0 @@
-
diff --git a/misc/svg/status/dot_online_notification.svg b/misc/svg/status/dot_online_notification.svg
deleted file mode 100644
index 4bf5500..0000000
--- a/misc/svg/status/dot_online_notification.svg
+++ /dev/null
@@ -1,7 +0,0 @@
-
diff --git a/misc/venom.desktop.in b/misc/venom.desktop.in
deleted file mode 100644
index bed6297..0000000
--- a/misc/venom.desktop.in
+++ /dev/null
@@ -1,11 +0,0 @@
-[Desktop Entry]
-Version=1.0
-Type=Application
-Name=Venom
-Comment=A GTK+/Vala GUI for Tox
-TryExec=venom
-Exec=venom %u
-Icon=venom
-Categories=InstantMessaging;Network;AudioVideo;GTK;
-Terminal=false
-MimeType=x-scheme-handler/tox;
diff --git a/misc/venom.ico b/misc/venom.ico
deleted file mode 100644
index 6efc6ac..0000000
Binary files a/misc/venom.ico and /dev/null differ
diff --git a/misc/venom.rc.in b/misc/venom.rc.in
deleted file mode 100644
index 713f667..0000000
--- a/misc/venom.rc.in
+++ /dev/null
@@ -1,44 +0,0 @@
-/*
- * Copyright (C) 2013 Venom authors and contributors
- *
- * This file is part of Venom.
- *
- * Venom is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * Venom is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with Venom. If not, see .
- */
-
-id ICON "venom.ico"
-VS_VERSION_INFO VERSIONINFO
-FILEVERSION @VENOM_VERSION_MAJOR@,@VENOM_VERSION_MINOR@,@VENOM_VERSION_PATCH@,0
-PRODUCTVERSION @VENOM_VERSION_MAJOR@,@VENOM_VERSION_MINOR@,@VENOM_VERSION_PATCH@,0
-BEGIN
- BLOCK "StringFileInfo"
- BEGIN
- BLOCK "040904B0"
- BEGIN
- VALUE "CompanyName", "Venom authors and contributors"
- VALUE "FileDescription", "@VENOM_SHORT_DESCRIPTION@"
- VALUE "FileVersion", "@VENOM_VERSION_MAJOR@.@VENOM_VERSION_MINOR@.@VENOM_VERSION_PATCH@.0"
- VALUE "InternalName", "venom"
- VALUE "LegalCopyright", "@VENOM_COPYRIGHT_NOTICE@"
- VALUE "OriginalFilename", "venom.exe"
- VALUE "ProductName", "Venom"
- VALUE "ProductVersion", "@VENOM_VERSION_MAJOR@.@VENOM_VERSION_MINOR@.@VENOM_VERSION_PATCH@"
- END
- END
-
- BLOCK "VarFileInfo"
- BEGIN
- VALUE "Translation", 0x409, 1200
- END
-END
diff --git a/po/.gitignore b/po/.gitignore
new file mode 100644
index 0000000..e8df44a
--- /dev/null
+++ b/po/.gitignore
@@ -0,0 +1,2 @@
+venom.pot
+*.mo
diff --git a/po/CMakeLists.txt b/po/CMakeLists.txt
deleted file mode 100644
index 7837852..0000000
--- a/po/CMakeLists.txt
+++ /dev/null
@@ -1,33 +0,0 @@
-#
-# Copyright (C) 2013-2014 Venom authors and contributors
-#
-# This file is part of Venom.
-#
-# Venom is free software: you can redistribute it and/or modify
-# it under the terms of the GNU General Public License as published by
-# the Free Software Foundation, either version 3 of the License, or
-# (at your option) any later version.
-#
-# Venom is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with Venom. If not, see .
-#
-
-SET(TRANSLATIONS
- de
- es
- it
- ru
- zh_CN
-)
-
-IF (XGETTEXT_FOUND)
- GETTEXT_CREATE_TRANSLATIONS(${GETTEXT_PACKAGE}.pot ALL ${TRANSLATIONS} COMMENT "Creating translations.")
-ELSE ()
- message(STATUS "xgettext not found")
-ENDIF()
-
diff --git a/po/LINGUAS b/po/LINGUAS
new file mode 100644
index 0000000..3038703
--- /dev/null
+++ b/po/LINGUAS
@@ -0,0 +1,8 @@
+de
+es
+fr
+it
+pl
+pr
+ru
+zh_CN
diff --git a/po/POTFILES b/po/POTFILES
new file mode 100644
index 0000000..b0a357c
--- /dev/null
+++ b/po/POTFILES
@@ -0,0 +1,129 @@
+src/Main.vala
+src/undo/UndoCommand.vala
+src/undo/UndoStack.vala
+src/undo/TextBufferUndoBinding.vala
+src/undo/SimpleUndoStack.vala
+src/testing/TestDhtNodeDb.vala
+src/testing/TestUndo.vala
+src/testing/ToxAVTest.vala
+src/testing/TestSqliteDb.vala
+src/testing/GroupBot.vala
+src/testing/TestToxAdapterFiletransferListener.vala
+src/testing/TestObservableList.vala
+src/testing/TestMessageDb.vala
+src/testing/ExamplePlugin.vala
+src/testing/TestMock.vala
+src/testing/TestAbout.vala
+src/testing/TestContact.vala
+src/testing/TestPlugin.vala
+src/testing/TestToxCore.vala
+src/testing/mocks/MockDb.vala
+src/testing/mocks/MockNotificationListener.vala
+src/testing/mocks/MockLogger.vala
+src/testing/mocks/MockDht.vala
+src/testing/mocks/MockMessageDb.vala
+src/testing/mocks/MockContact.vala
+src/testing/mocks/MockToxSession.vala
+src/testing/mocks/MockFiletransfer.vala
+src/testing/util/MockFramework.vala
+src/testing/util/UnitTest.vala
+src/testing/util/Assert.vala
+src/testing/TestJsonWebDhtNodeDb.vala
+src/testing/TestGlibTesting.vala
+src/core/Interfaces.vala
+src/core/NotificationListener.vala
+src/core/UserInfo.vala
+src/core/TimeStamp.vala
+src/core/FileTransfer.vala
+src/core/R.vala
+src/core/Logger.vala
+src/core/Message.vala
+src/core/Contact.vala
+src/core/FileIO.vala
+src/core/WidgetFactory.vala
+src/core/Tools.vala
+src/core/WindowState.vala
+src/core/Application.vala
+src/core/ObservableList.vala
+src/core/AVManager.vala
+src/viewmodel/UserInfoViewModel.vala
+src/viewmodel/ContactListViewModel.vala
+src/viewmodel/FriendInfoViewModel.vala
+src/viewmodel/AddContactViewModel.vala
+src/viewmodel/ContactListEntryViewModel.vala
+src/viewmodel/MessageViewModel.vala
+src/viewmodel/FileTransferEntryViewModel.vala
+src/viewmodel/CreateGroupchatViewModel.vala
+src/viewmodel/ConferenceInfoViewModel.vala
+src/tox/ToxSessionIO.vala
+src/tox/DhtNodeDatabase.vala
+src/tox/ToxAdapterFriendListener.vala
+src/tox/ContactDatabase.vala
+src/tox/ToxAdapterFiletransferListener.vala
+src/tox/Conference.vala
+src/tox/FriendRequest.vala
+src/tox/ToxSessionThread.vala
+src/tox/ToxContact.vala
+src/tox/ToxSession.vala
+src/tox/JsonWebDhtNodeDatabase.vala
+src/tox/DhtNode.vala
+src/tox/SqliteDhtNodeDatabase.vala
+src/tox/ToxAdapterSelfListener.vala
+src/tox/ToxAdapterConferenceListener.vala
+src/tox/MessageDatabase.vala
+src/tox/ConferenceMessage.vala
+src/plugin/Plugin.vala
+src/plugin/Pluginregistrar.vala
+src/view/MessageWidget.vala
+src/view/ConferenceInfoWidget.vala
+src/view/ApplicationWindow.vala
+src/view/ConferenceWindow.vala
+src/view/NodeWidget.vala
+src/view/AboutDialog.vala
+src/view/ContactListRequestEntry.vala
+src/view/WelcomeWidget.vala
+src/view/FileTransferEntryInline.vala
+src/view/FileTransferWidget.vala
+src/view/FriendRequestWidget.vala
+src/view/ContactListEntry.vala
+src/view/ContactListWidget.vala
+src/view/SettingsWidget.vala
+src/view/CreateGroupchatWidget.vala
+src/view/AddContactWidget.vala
+src/view/ConversationWindow.vala
+src/view/PeerEntry.vala
+src/view/FileTransferEntry.vala
+src/view/ConferenceInviteEntry.vala
+src/view/UserInfoWidget.vala
+src/view/FriendInfoWidget.vala
+src/view/ContextStyleBinding.vala
+src/ui/file_transfer_widget.ui
+src/ui/application_window.ui
+src/ui/file_transfer_entry.ui
+src/ui/create_groupchat_widget.ui
+src/ui/peer_entry_compact.ui
+src/ui/conference_window.ui
+src/ui/app_menu.ui
+src/ui/contact_list_widget.ui
+src/ui/conversation_window.ui
+src/ui/friend_request_widget.ui
+src/ui/conference_info_widget.ui
+src/ui/peer_entry.ui
+src/ui/welcome_widget.ui
+src/ui/conference_invite_entry.ui
+src/ui/node_widget.ui
+src/ui/message_widget.ui
+src/ui/user_status_menu.ui
+src/ui/add_contact_widget.ui
+src/ui/user_info_widget.ui
+src/ui/contact_list_entry.ui
+src/ui/file_transfer_entry_inline.ui
+src/ui/settings_widget.ui
+src/ui/contact_list_request_entry.ui
+src/ui/friend_info_widget.ui
+src/db/DatabaseInterfaces.vala
+src/db/SqliteWrapper.vala
+src/db/SqliteSettingsDatabase.vala
+src/portal/Request.vala
+src/portal/Screenshot.vala
+data/chat.tox.venom.desktop.in
diff --git a/po/Venom.pot b/po/Venom.pot
deleted file mode 100644
index b85095b..0000000
--- a/po/Venom.pot
+++ /dev/null
@@ -1,1015 +0,0 @@
-# SOME DESCRIPTIVE TITLE.
-# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
-# This file is distributed under the same license as the PACKAGE package.
-# FIRST AUTHOR , YEAR.
-#
-#, fuzzy
-msgid ""
-msgstr ""
-"Project-Id-Version: Venom \n"
-"Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2014-06-17 21:05+0200\n"
-"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
-"Last-Translator: FULL NAME \n"
-"Language-Team: LANGUAGE \n"
-"Language: \n"
-"MIME-Version: 1.0\n"
-"Content-Type: text/plain; charset=CHARSET\n"
-"Content-Transfer-Encoding: 8bit\n"
-
-#: core/ToxSession.vala:725
-#, c-format
-msgid " %s\n"
-msgstr ""
-
-#: core/DhtNode.vala:47
-msgid " (ipv6)"
-msgstr ""
-
-#: ui/ContactListWindow.vala:627
-#, c-format
-msgid "%F"
-msgstr ""
-
-#: core/Message.vala:47
-msgid "%R:%S"
-msgstr ""
-
-#: core/GroupChat.vala:52
-#, c-format
-msgid "%i people connected"
-msgstr ""
-
-#: core/GroupChat.vala:54
-#, c-format
-msgid "%i person connected"
-msgstr ""
-
-#: core/Contact.vala:69 core/Contact.vala:83
-#, c-format
-msgid "%s (%s)"
-msgstr ""
-
-#: ui/ContactListWindow.vala:648
-#, c-format
-msgid "%s changed his name to %s\n"
-msgstr ""
-
-#: ui/ContactListWindow.vala:652
-#, c-format
-msgid "%s changed his status to %s\n"
-msgstr ""
-
-#: ui/ContactListWindow.vala:663
-#, c-format
-msgid "%s is now %s.\n"
-msgstr ""
-
-#: ui/ConversationWidget.vala:60
-#, c-format
-msgid "%s is typing..."
-msgstr ""
-
-#: ui/ContactListWindow.vala:131
-#, c-format
-msgid "%s: %s\n"
-msgstr ""
-
-#: core/DhtNode.vala:47
-#, c-format
-msgid "%s:%u%s %s"
-msgstr ""
-
-#: ui/ContactListWindow.vala:714
-#, c-format
-msgid "'%s' has invited you to a groupchat, do you want to accept?"
-msgstr ""
-
-#: ui/ContactListWindow.vala:577
-#, c-format
-msgid "* %s"
-msgstr ""
-
-#: ui/ContactListWindow.vala:627
-#, c-format
-msgid "<%i>"
-msgstr ""
-
-#: ui/ContactListWindow.vala:627
-#, c-format
-msgid "<%s> %s:%s\n"
-msgstr ""
-
-#: ui/ConversationWidget.vala:51 ui/GroupConversationWidget.vala:47
-#, c-format
-msgid "%s"
-msgstr ""
-
-#: core/Contact.vala:72 core/Contact.vala:86 ui/ConversationView.vala:55
-#, c-format
-msgid "%s"
-msgstr ""
-
-#: core/Message.vala:152 core/Message.vala:191
-msgid ""
-msgstr ""
-
-#: ui/AddContactDialog.vala:76
-msgid "Add contact"
-msgstr ""
-
-#: ui/ContactListWindow.vala:617
-#, c-format
-msgid "Added new friend #%i\n"
-msgstr ""
-
-#: ui/ContactListWindow.vala:1125 ui/ContactListWindow.vala:1137
-msgid "Adding Friend failed"
-msgstr ""
-
-#: ui/ContactListWindow.vala:210
-msgid "All"
-msgstr ""
-
-#: ui/ContactListWindow.vala:1060 ui/ContactListWindow.vala:1082
-#, c-format
-msgid "Are you sure you want to delete '%s' from your contact list?"
-msgstr ""
-
-#: core/ToxSession.vala:33
-msgid "Away"
-msgstr ""
-
-#: core/ToxSession.vala:717
-#, c-format
-msgid "Background thread started.\n"
-msgstr ""
-
-#: core/ToxSession.vala:756
-#, c-format
-msgid "Background thread stopped.\n"
-msgstr ""
-
-#: core/Tools.vala:142
-msgid "Bad checksum"
-msgstr ""
-
-#: core/ToxSession.vala:35
-msgid "Busy"
-msgstr ""
-
-#: core/Tools.vala:158 core/Tools.vala:171
-#, c-format
-msgid "Can't create action regex: %s.\n"
-msgstr ""
-
-#: core/SqliteTools.vala:75
-#, c-format
-msgid "Can't open database: %d: %s\n"
-msgstr ""
-
-#: core/Tools.vala:136
-msgid "Can't send to own key"
-msgstr ""
-
-#: ui/FileTransferChatEntry.vala:119
-msgid "Canceled"
-msgstr ""
-
-#: ui/ContactListWindow.vala:670
-msgid "Connected to the network"
-msgstr ""
-
-#: core/ToxSession.vala:720
-#, c-format
-msgid "Connecting to DHT Nodes:\n"
-msgstr ""
-
-#: ui/ContactListWindow.vala:668
-#, c-format
-msgid "Connection to DHT %s.\n"
-msgstr ""
-
-#: ui/ContactListWindow.vala:907
-#, c-format
-msgid "Contact accepted file sending request\n"
-msgstr ""
-
-#: ui/ContactListWindow.vala:508
-#, c-format
-msgid "Copied Tox ID to clipboard\n"
-msgstr ""
-
-#: ui/ContactListWindow.vala:1135
-#, c-format
-msgid "Could not add friend: %s.\n"
-msgstr ""
-
-#: ui/ContactListWindow.vala:1123
-msgid "Could not add friend: Invalid ID\n"
-msgstr ""
-
-#: core/SqliteTools.vala:40
-#, c-format
-msgid "Could not bind int to %s."
-msgstr ""
-
-#: core/SqliteTools.vala:50
-#, c-format
-msgid "Could not bind int64 to %s."
-msgstr ""
-
-#: core/SqliteTools.vala:60
-#, c-format
-msgid "Could not bind text to %s"
-msgstr ""
-
-#: ui/ContactListWindow.vala:447
-#, c-format
-msgid "Could not change user name!\n"
-msgstr ""
-
-#: ui/ContactListWindow.vala:455
-#, c-format
-msgid "Could not change user statusmessage!\n"
-msgstr ""
-
-#: ui/ContactListWindow.vala:1189
-#, c-format
-msgid "Could not create a new groupchat.\n"
-msgstr ""
-
-#: ui/ContactListWindow.vala:725
-#, c-format
-msgid "Could not join groupchat.\n"
-msgstr ""
-
-#: ui/ContactListWindow.vala:146
-#, c-format
-msgid "Could not load session data (%s), creating new one.\n"
-msgstr ""
-
-#: ui/ContactListWindow.vala:130
-#, c-format
-msgid "Could not read theme from \"%s\""
-msgstr ""
-
-#: ui/ContactListWindow.vala:1090
-#, c-format
-msgid "Could not remove %s.\n"
-msgstr ""
-
-#: ui/ContactListWindow.vala:1068
-#, c-format
-msgid "Could not remove contact %i.\n"
-msgstr ""
-
-#: core/ToxSession.vala:352
-#, c-format
-msgid "Could not remove peer [%i] from groupchat #%i (no such peer)\n"
-msgstr ""
-
-#: ui/ContactListWindow.vala:1112
-msgid "Could not resolve ID from DNS record\n"
-msgstr ""
-
-#: ui/FileTransferChatEntry.vala:125 ui/FileTransferChatEntry.vala:129
-msgid "Disconnected"
-msgstr ""
-
-#: ui/ContactListWindow.vala:673
-msgid "Disconnected from the network"
-msgstr ""
-
-#: ui/UserInfoWindow.vala:86
-msgid "Edit user information"
-msgstr ""
-
-#: ui/ContactListWindow.vala:899
-#, c-format
-msgid "Ended file transfer for %s to %s\n"
-msgstr ""
-
-#: ui/ContactListWindow.vala:102
-#, c-format
-msgid "Ending session...\n"
-msgstr ""
-
-#: core/ContactStorage.vala:108
-#, c-format
-msgid "Error creating contacts insert statement: %d: %s\n"
-msgstr ""
-
-#: core/ContactStorage.vala:113
-#, c-format
-msgid "Error creating contacts select statement: %d: %s\n"
-msgstr ""
-
-#: core/ContactStorage.vala:103
-#, c-format
-msgid "Error creating contacts table: %s\n"
-msgstr ""
-
-#: core/DhtNodeStorage.vala:177
-#, c-format
-msgid "Error creating dht nodes insert statement: %d: %s\n"
-msgstr ""
-
-#: core/DhtNodeStorage.vala:182
-#, c-format
-msgid "Error creating dht nodes select statement: %d: %s\n"
-msgstr ""
-
-#: core/DhtNodeStorage.vala:172
-#, c-format
-msgid "Error creating dht nodes table: %s\n"
-msgstr ""
-
-#: core/ToxDns.vala:36
-#, c-format
-msgid "Error creating tox dns regex: %s\n"
-msgstr ""
-
-#: core/ToxDns.vala:51
-#, c-format
-msgid "Error creating tox uri regex: %s\n"
-msgstr ""
-
-#: ui/ConversationTextView.vala:184
-#, c-format
-msgid "Error matching uri regex: %s\n"
-msgstr ""
-
-#: ui/ConversationWidget.vala:308
-#, c-format
-msgid "Error occured while getting file size: %s"
-msgstr ""
-
-#: core/ToxSession.vala:111
-#, c-format
-msgid "Error opening database: %s\n"
-msgstr ""
-
-#: core/Settings.vala:112
-#, c-format
-msgid "Error reading configs:%s\n"
-msgstr ""
-
-#: core/ToxDns.vala:81
-#, c-format
-msgid "Error resolving name: %s\n"
-msgstr ""
-
-#: core/MessageLog.vala:135
-#, c-format
-msgid "Error retrieving logs from sqlite database: %s\n"
-msgstr ""
-
-#: core/Settings.vala:99
-#, c-format
-msgid "Error saving configs:%s\n"
-msgstr ""
-
-#: core/Tools.vala:123
-#, c-format
-msgid "Error when doing uri markup: %s"
-msgstr ""
-
-#: ui/ConversationTextView.vala:245
-#, c-format
-msgid "Error when showing uri: %s\n"
-msgstr ""
-
-#: ui/ContactListWindow.vala:168
-#, c-format
-msgid "Error while loading icon: %s\n"
-msgstr ""
-
-#: core/ResourceFactory.vala:126
-#, c-format
-msgid "Error while loading image from \"%s\":%s\n"
-msgstr ""
-
-#: core/ToxSession.vala:801
-msgid "Error while loading messenger data."
-msgstr ""
-
-#: core/ToxSession.vala:795
-msgid "Error while reading from stream."
-msgstr ""
-
-#: ui/FileTransferChatEntry.vala:171
-#, c-format
-msgid "Error while trying to create file: %s\n"
-msgstr ""
-
-#: ui/ContactListWindow.vala:961
-#, c-format
-msgid "Error while trying to write data to file\n"
-msgstr ""
-
-#: core/ToxSession.vala:828
-msgid "Error while writing to stream."
-msgstr ""
-
-#: core/ContactStorage.vala:88
-#, c-format
-msgid "Error writing contact to sqlite database: %s\n"
-msgstr ""
-
-#: core/MessageLog.vala:118
-#, c-format
-msgid "Error writing message to sqlite database: %s\n"
-msgstr ""
-
-#: core/MessageLog.vala:186 core/MessageLog.vala:193
-#, c-format
-msgid "Error: %d: %s\n"
-msgstr ""
-
-#: core/MessageLog.vala:169 core/MessageLog.vala:179
-#: ui/ConversationView.vala:78
-#, c-format
-msgid "Error: %s\n"
-msgstr ""
-
-#: core/ToxSession.vala:788
-#, c-format
-msgid "File \"%d\" does not exist."
-msgstr ""
-
-#: ui/ContactListWindow.vala:929
-#, c-format
-msgid "File transfer finished for file number %u"
-msgstr ""
-
-#: ui/ContactListWindow.vala:925
-#, c-format
-msgid "File transfer was rejected for file number %u"
-msgstr ""
-
-#: ui/FileTransferChatEntry.vala:94
-msgid "File was rejected"
-msgstr ""
-
-#: ui/ContactListWindow.vala:614
-#, c-format
-msgid "Friend could not be added.\n"
-msgstr ""
-
-#: core/Tools.vala:138
-msgid "Friend request already sent"
-msgstr ""
-
-#: core/Tools.vala:148
-msgid "Friend request successfully sent"
-msgstr ""
-
-#: ui/ContactListWindow.vala:1142
-#, c-format
-msgid "Friend request successfully sent. Friend added as %i.\n"
-msgstr ""
-
-#: ui/ContactListWindow.vala:771
-#, c-format
-msgid "Group action from unknown contact #%i [%i]\n"
-msgstr ""
-
-#: ui/ContactListWindow.vala:708
-#, c-format
-msgid "Group invite from %s with public key %s\n"
-msgstr ""
-
-#: ui/ContactListWindow.vala:742
-#, c-format
-msgid "Group message from unknown contact #%i [%i]\n"
-msgstr ""
-
-#: core/GroupChat.vala:45
-#, c-format
-msgid "Groupchat #%i"
-msgstr ""
-
-#: ui/ContactListWindow.vala:896
-#, c-format
-msgid "I/O error while trying to close file stream: %s\n"
-msgstr ""
-
-#: ui/ContactListWindow.vala:888
-#, c-format
-msgid "I/O error while trying to read file: %s\n"
-msgstr ""
-
-#: ui/AddContactDialog.vala:96
-msgid "ID contains invalid characters"
-msgstr ""
-
-#: ui/ContactListWindow.vala:86
-#, c-format
-msgid "ID: %s\n"
-msgstr ""
-
-#: core/SqliteTools.vala:37 core/SqliteTools.vala:47 core/SqliteTools.vala:57
-#, c-format
-msgid "Index for %s not found."
-msgstr ""
-
-#: core/ToxDns.vala:113
-#, c-format
-msgid "Invalid record\n"
-msgstr ""
-
-#: core/ToxDns.vala:64
-#, c-format
-msgid "Invalid tox uri\n"
-msgstr ""
-
-#: ui/ContactListWindow.vala:728
-#, c-format
-msgid "Joined Groupchat #%i\n"
-msgstr ""
-
-#: core/Contact.vala:117
-#, c-format
-msgid "Last seen: %s"
-msgstr ""
-
-#: ui/AddContactDialog.vala:53
-#, c-format
-msgid "Loading add contact window failed!\n"
-msgstr ""
-
-#: ui/ConversationWidget.vala:71 ui/SettingsWindow.vala:32
-#, c-format
-msgid "Loading conversation window failed!\n"
-msgstr ""
-
-#: ui/FileTransferChatEntry.vala:40
-#, c-format
-msgid "Loading message widget failed!\n"
-msgstr ""
-
-#: core/Tools.vala:132
-msgid "Message too long"
-msgstr ""
-
-#: ui/ContactListWindow.vala:604
-#, c-format
-msgid ""
-"New friend request from '%s'.\n"
-"Do you want to accept?"
-msgstr ""
-
-#: ui/AddContactDialog.vala:90
-msgid "No ID given"
-msgstr ""
-
-#: core/Tools.vala:134
-msgid "No message included"
-msgstr ""
-
-#: core/ToxDns.vala:103
-#, c-format
-msgid "No pin privided, aborting...\n"
-msgstr ""
-
-#: core/Contact.vala:98 core/Contact.vala:108 core/ToxSession.vala:37
-msgid "Offline"
-msgstr ""
-
-#: core/GroupChatContact.vala:32 core/ToxSession.vala:31
-#: ui/ContactListWindow.vala:208
-msgid "Online"
-msgstr ""
-
-#: core/Tools.vala:146
-msgid "Out of memory"
-msgstr ""
-
-#: ui/FileTransferChatEntry.vala:104
-msgid "Paused"
-msgstr ""
-
-#: ui/PinDialog.vala:37
-#, c-format
-msgid ""
-"Please insert PIN for \n"
-"%s"
-msgstr ""
-
-#: ui/PinDialog.vala:49
-msgid "Please insert PIN..."
-msgstr ""
-
-#: ui/ContactListWindow.vala:869
-#, c-format
-msgid "Read incorrect number of bytes from file\n"
-msgstr ""
-
-#: ui/FileTransferChatEntry.vala:113
-msgid "Receiving failed"
-msgstr ""
-
-#: ui/ContactListWindow.vala:1114
-msgid "Resolving ID failed"
-msgstr ""
-
-#: ui/ContactListWindow.vala:427
-#, c-format
-msgid "Retrieved contact %s from savefile.\n"
-msgstr ""
-
-#: Main.vala:50
-#, c-format
-msgid "Run '%s --help' to see a full list of available command line options.\n"
-msgstr ""
-
-#: core/MessageLog.vala:86
-#, c-format
-msgid "SQLite database closed.\n"
-msgstr ""
-
-#: core/MessageLog.vala:82
-#, c-format
-msgid "SQLite database created.\n"
-msgstr ""
-
-#: ui/FileTransferChatEntry.vala:158
-msgid "Save"
-msgstr ""
-
-#: ui/FileTransferChatEntry.vala:155
-msgid "Save file"
-msgstr ""
-
-#: ui/ContactListWindow.vala:120
-#, c-format
-msgid "Saving session file failed: %s\n"
-msgstr ""
-
-#: ui/FileTransferChatEntry.vala:165
-#, c-format
-msgid "Saving to: %s\n"
-msgstr ""
-
-#: ui/ContactListWindow.vala:116
-#, c-format
-msgid "Saving tox session data\n"
-msgstr ""
-
-#: ui/ConversationWidget.vala:282
-msgid "Select"
-msgstr ""
-
-#: ui/ConversationWidget.vala:279
-msgid "Select a file to send"
-msgstr ""
-
-#: ui/FileTransferChatEntry.vala:107
-msgid "Sending failed"
-msgstr ""
-
-#: ui/ContactListWindow.vala:111
-#, c-format
-msgid "Session ended gracefully.\n"
-msgstr ""
-
-#: core/Tools.vala:144
-msgid "Set new nospam"
-msgstr ""
-
-#: core/Settings.vala:102
-#, c-format
-msgid "Settings saved.\n"
-msgstr ""
-
-#: Main.vala:70
-#, c-format
-msgid "Starting in offline mode\n"
-msgstr ""
-
-#: ui/ContactListWindow.vala:408
-#, c-format
-msgid "Theme refreshed\n"
-msgstr ""
-
-#: ui/Client.vala:116
-msgid "There is currently no help available"
-msgstr ""
-
-#: core/ResourceFactory.vala:77
-msgid "Tox User"
-msgstr ""
-
-#: core/ResourceFactory.vala:78
-#, c-format
-msgid "Toxing on Venom v.%s"
-msgstr ""
-
-#: ui/ContactListWindow.vala:826
-#, c-format
-msgid "Trying to send unknown file"
-msgstr ""
-
-#: ui/MessageTextView.vala:27
-msgid "Type your message here..."
-msgstr ""
-
-#: core/Tools.vala:140
-msgid "Unknown error"
-msgstr ""
-
-#: ui/ContactListWindow.vala:890
-#, c-format
-msgid "Unknown error while trying to read file: %s\n"
-msgstr ""
-
-#: Main.vala:65
-#, c-format
-msgid "Using Gtk.TextView to display messages\n"
-msgstr ""
-
-#: Main.vala:60
-#, c-format
-msgid "Using data file \"%s\"\n"
-msgstr ""
-
-#: ui/AddContactDialog.vala:100
-msgid "Valid ID size"
-msgstr ""
-
-#: ui/ContactListWindow.vala:461
-#, c-format
-msgid "Venom (%s)"
-msgstr ""
-
-#: ui/ConversationTextView.vala:139
-#, c-format
-msgid "[%s] "
-msgstr ""
-
-#: ui/ContactListWindow.vala:638
-#, c-format
-msgid "[ac] %i:%s\n"
-msgstr ""
-
-#: ui/ContactListWindow.vala:598
-#, c-format
-msgid "[fr] %s:%s\n"
-msgstr ""
-
-#: ui/ContactListWindow.vala:763
-#, c-format
-msgid "[ga] %s [%i]@%i: %s\n"
-msgstr ""
-
-#: ui/ContactListWindow.vala:734
-#, c-format
-msgid "[gm] %s [%i]@%i: %s\n"
-msgstr ""
-
-#: ui/ContactListWindow.vala:660
-#, c-format
-msgid "[rr] %s:%u\n"
-msgstr ""
-
-#: ui/ContactListWindow.vala:656
-#, c-format
-msgid "[us] %s:%i\n"
-msgstr ""
-
-#: Main.vala:49
-#, c-format
-msgid "error: %s\n"
-msgstr ""
-
-#: ui/ContactListWindow.vala:668
-msgid "established"
-msgstr ""
-
-#: ui/ContactListWindow.vala:569
-#, c-format
-msgid "failed to send file %s to %s"
-msgstr ""
-
-#: ui/ContactListWindow.vala:1077
-#, c-format
-msgid "groupchat #%i"
-msgstr ""
-
-#: ui/ContactListWindow.vala:668
-msgid "lost"
-msgstr ""
-
-#: core/GroupChat.vala:56
-msgid "no one connected"
-msgstr ""
-
-#: ui/ContactListWindow.vala:663
-msgid "offline"
-msgstr ""
-
-#: ui/ContactListWindow.vala:663
-msgid "online"
-msgstr ""
-
-#: ui/ContactListWindow.vala:798
-#, c-format
-msgid "received file send request friend: %i filenumber: %i filename: %s \n"
-msgstr ""
-
-#: ui/ContactListWindow.vala:562
-#, c-format
-msgid "sending file %s to %s\n"
-msgstr ""
-
-#: ui/ContactListWindow.vala:1129
-#, c-format
-msgid "setting alias: %s\n"
-msgstr ""
-
-#: core/ToxDns.vala:95
-#, c-format
-msgid "tox 1 ID found: %s\n"
-msgstr ""
-
-#: core/ToxDns.vala:100
-#, c-format
-msgid "tox 2 ID found: %s %s\n"
-msgstr ""
-
-#: ui/AboutDialog.vala:46
-msgid "translator-credits"
-msgstr ""
-
-#: ui/add_contact_dialog.ui:6
-msgid "Please let me add you to my contact list."
-msgstr ""
-
-#: ui/add_contact_dialog.ui:27
-msgid "_Tox ID:"
-msgstr ""
-
-#: ui/add_contact_dialog.ui:40
-msgid "Enter a Tox ID here or a Tox URI"
-msgstr ""
-
-#: ui/add_contact_dialog.ui:54
-msgid "_Nickname (optional):"
-msgstr ""
-
-#: ui/add_contact_dialog.ui:67
-msgid "Set a custom nickname for the friend you are about to add"
-msgstr ""
-
-#: ui/add_contact_dialog.ui:94
-msgid "_Message (optional):"
-msgstr ""
-
-#: ui/add_contact_dialog.ui:113
-msgid "Send a custom message to be displayed to the friend you are adding"
-msgstr ""
-
-#: ui/contact_list.ui:50
-msgid "_Edit user"
-msgstr ""
-
-#: ui/contact_list.ui:61
-msgid "_Copy ID to clipboard"
-msgstr ""
-
-#: ui/contact_list.ui:72
-msgid "Change _Status"
-msgstr ""
-
-#: ui/contact_list.ui:85
-msgid "_Online"
-msgstr ""
-
-#: ui/contact_list.ui:96
-msgid "_Away"
-msgstr ""
-
-#: ui/contact_list.ui:107
-msgid "_Busy"
-msgstr ""
-
-#: ui/contact_list.ui:118
-msgid "O_ffline"
-msgstr ""
-
-#: ui/contact_list.ui:278
-msgid "connecting..."
-msgstr ""
-
-#: ui/contact_list.ui:416
-msgid "Create groupchat"
-msgstr ""
-
-#: ui/contact_list.ui:449
-msgid "Open preferences"
-msgstr ""
-
-#: ui/conversation_window.ui:156
-msgid "Call contact"
-msgstr ""
-
-#: ui/conversation_window.ui:174
-msgid "Call contact with video"
-msgstr ""
-
-#: ui/conversation_window.ui:290
-msgid "Insert Smiley"
-msgstr ""
-
-#: ui/conversation_window.ui:308
-msgid "Send file"
-msgstr ""
-
-#: ui/conversation_window.ui:341
-msgid "Send message"
-msgstr ""
-
-#: ui/settings_window.ui:14
-msgid "KiB/MiB"
-msgstr ""
-
-#: ui/settings_window.ui:18
-msgid "KB/MB"
-msgstr ""
-
-#: ui/settings_window.ui:30
-msgid "Settings"
-msgstr ""
-
-#: ui/settings_window.ui:78
-msgid "Keep history"
-msgstr ""
-
-#: ui/settings_window.ui:104
-msgid "indefinitely"
-msgstr ""
-
-#: ui/settings_window.ui:127
-msgid "delete after"
-msgstr ""
-
-#: ui/settings_window.ui:160
-msgid "days"
-msgstr ""
-
-#: ui/settings_window.ui:186
-msgid "Show _others when I am typing"
-msgstr ""
-
-#: ui/settings_window.ui:202
-msgid "Show me when others are typing"
-msgstr ""
-
-#: ui/settings_window.ui:221
-msgid "Privacy"
-msgstr ""
-
-#: ui/settings_window.ui:236
-msgid "Flash window when a new message arrives"
-msgstr ""
-
-#: ui/settings_window.ui:258
-msgid "Show filesize in"
-msgstr ""
-
-#: ui/settings_window.ui:301
-msgid "Default Tox DNS ID suffix:"
-msgstr ""
-
-#: ui/settings_window.ui:337
-msgid "Miscellaneous"
-msgstr ""
-
-#: ui/user_info_window.ui:40
-msgid "ID:"
-msgstr ""
-
-#: ui/user_info_window.ui:119
-msgid "Tox"
-msgstr ""
-
-#: ui/user_info_window.ui:178
-msgid "Status message:"
-msgstr ""
-
-#: ui/user_info_window.ui:192
-msgid "Name:"
-msgstr ""
-
-#: ui/user_info_window.ui:222
-msgid "Icon:"
-msgstr ""
-
-#: ui/user_info_window.ui:254
-msgid "_Browse..."
-msgstr ""
-
-#: ui/user_info_window.ui:282
-msgid "User"
-msgstr ""
diff --git a/po/de.po b/po/de.po
index 35af217..6ad69bb 100644
--- a/po/de.po
+++ b/po/de.po
@@ -1,1037 +1,705 @@
-# German translations for PACKAGE package.
-# Copyright (C) 2014 THE PACKAGE'S COPYRIGHT HOLDER
-# This file is distributed under the same license as the PACKAGE package.
-# , 2014.
-#
msgid ""
msgstr ""
-"Project-Id-Version: Venom\n"
-"Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2014-06-17 21:05+0200\n"
-"PO-Revision-Date: 2014-06-17 21:09+0100\n"
-"Last-Translator: Spixi \n"
-"Language-Team: German\n"
-"Language: de\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
+"X-Generator: POEditor.com\n"
+"Project-Id-Version: Venom\n"
+"Language: de\n"
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
-"X-Generator: Poedit 1.6.5\n"
-
-#: core/ToxSession.vala:725
-#, c-format
-msgid " %s\n"
-msgstr " %s\n"
-
-#: core/DhtNode.vala:47
-msgid " (ipv6)"
-msgstr " (IPv6)"
-
-#: ui/ContactListWindow.vala:627
-#, c-format
-msgid "%F"
-msgstr "%F"
-
-#: core/Message.vala:47
-msgid "%R:%S"
-msgstr "%R:%S"
-
-#: core/GroupChat.vala:52
-#, c-format
-msgid "%i people connected"
-msgstr "%i Leute verbunden"
-
-#: core/GroupChat.vala:54
-#, c-format
-msgid "%i person connected"
-msgstr "%i Person verbunden"
-
-#: core/Contact.vala:69 core/Contact.vala:83
-#, c-format
-msgid "%s (%s)"
-msgstr "%s (%s)"
-
-#: ui/ContactListWindow.vala:648
-#, c-format
-msgid "%s changed his name to %s\n"
-msgstr "%s hat seinen Namen in %s geändert\n"
-
-#: ui/ContactListWindow.vala:652
-#, c-format
-msgid "%s changed his status to %s\n"
-msgstr "%s hat seinen Status nach %s geändert\n"
-
-#: ui/ContactListWindow.vala:663
-#, c-format
-msgid "%s is now %s.\n"
-msgstr "%s ist jetzt %s.\n"
-
-#: ui/ConversationWidget.vala:60
-#, c-format
-msgid "%s is typing..."
-msgstr "%s tippt gerade..."
-
-#: ui/ContactListWindow.vala:131
-#, c-format
-msgid "%s: %s\n"
-msgstr "%s: %s\n"
-
-#: core/DhtNode.vala:47
-#, c-format
-msgid "%s:%u%s %s"
-msgstr "%s:%u%s %s"
-
-#: ui/ContactListWindow.vala:714
-#, c-format
-msgid "'%s' has invited you to a groupchat, do you want to accept?"
-msgstr ""
-"'%s' hat dich zu einem Gruppenchat eingeladen, möchtest du die Einladung "
-"annehmen?"
-
-#: ui/ContactListWindow.vala:577
-#, c-format
-msgid "* %s"
-msgstr "* %s"
-
-#: ui/ContactListWindow.vala:627
-#, c-format
-msgid "<%i>"
-msgstr "<%i>"
-
-#: ui/ContactListWindow.vala:627
-#, c-format
-msgid "<%s> %s:%s\n"
-msgstr "<%s> %s:%s\n"
-
-#: ui/ConversationWidget.vala:51 ui/GroupConversationWidget.vala:47
-#, c-format
-msgid "%s"
-msgstr "%s"
-
-#: ui/user_info_window.ui:119
-msgid "Tox"
-msgstr "Tox"
-
-#: ui/user_info_window.ui:282
-msgid "User"
-msgstr "User"
-
-#: core/Contact.vala:72 core/Contact.vala:86 ui/ConversationView.vala:55
-#, c-format
-msgid "%s"
-msgstr "%s"
-
-#: core/Message.vala:152 core/Message.vala:191
-msgid ""
-msgstr ""
-
-#: ui/AddContactDialog.vala:76
-msgid "Add contact"
-msgstr "Kontakt hinzufügen"
-#: ui/ContactListWindow.vala:617
-#, c-format
-msgid "Added new friend #%i\n"
-msgstr "Neuen Freund #%i hinzugefügt\n"
+#: src/core/Application.vala:32
+msgid "Set level of messages to log"
+msgstr "Setze das Niveau für Protokollmeldungen"
-#: ui/ContactListWindow.vala:1125 ui/ContactListWindow.vala:1137
-msgid "Adding Friend failed"
-msgstr "Freund konnte nicht hinzugefügt werden"
+#: src/core/Application.vala:32
+msgid ""
+msgstr ""
-#: ui/ContactListWindow.vala:210
-msgid "All"
-msgstr "Alle"
+#: src/core/Application.vala:33
+msgid "Display version number"
+msgstr "Zeige Versionsnummer"
-#: ui/ContactListWindow.vala:1060 ui/ContactListWindow.vala:1082
-#, c-format
-msgid "Are you sure you want to delete '%s' from your contact list?"
-msgstr ""
-"Bist du sicher, dass du '%s' von deiner Kontaktliste entfernen möchtest?"
+#: src/core/NotificationListener.vala:55
+msgid "New message from %s"
+msgstr "Neue Nachricht von %s"
-#: core/ToxSession.vala:33
-msgid "Away"
-msgstr "Abwesend"
+#: src/core/R.vala:70
+msgid "Tox User"
+msgstr "Tox Nutzer"
-#: core/ToxSession.vala:717
-#, c-format
-msgid "Background thread started.\n"
-msgstr "Hintergrundthread gestartet.\n"
+#: src/tox/Conference.vala:48
+msgid "%u Peers online"
+msgstr "%u Mitglieder online"
-#: core/ToxSession.vala:756
-#, c-format
-msgid "Background thread stopped.\n"
-msgstr "Hintergrundthread beendet.\n"
+#: src/view/AboutDialog.vala:53
+msgid "Packagers"
+msgstr "Verpacker"
-#: core/Tools.vala:142
-msgid "Bad checksum"
-msgstr "Fehlerhafte Prüfsumme"
+#: src/view/AboutDialog.vala:58
+msgid "translator-credits"
+msgstr "Spixi , naxuroqa "
-#: core/ToxSession.vala:35
-msgid "Busy"
-msgstr "Beschäftigt"
+#: src/ui/add_contact_widget.ui:65
+msgid "Please let me add you to my contact list. 😁"
+msgstr "Bitte lass mich dich meiner Kontaktliste hinzufügen. 😁"
-#: ui/conversation_window.ui:156
-msgid "Call contact"
-msgstr "Kontakt anrufen"
-
-#: ui/conversation_window.ui:174
-msgid "Call contact with video"
-msgstr "Kontakt mit Video anrufen"
-
-#: core/Tools.vala:158 core/Tools.vala:171
-#, c-format
-msgid "Can't create action regex: %s.\n"
-msgstr "Konnte den Aktions-Regex nicht erstellen: %s\n"
-
-#: core/SqliteTools.vala:75
-#, c-format
-msgid "Can't open database: %d: %s\n"
-msgstr "Datenbank %d: %s konnte nicht geöffnet werden\n"
-
-#: core/Tools.vala:136
-msgid "Can't send to own key"
-msgstr "Kann nicht an eigenen Schlüssel senden"
-
-#: ui/FileTransferChatEntry.vala:119
-msgid "Canceled"
-msgstr "Abgebrochen"
-
-#: ui/contact_list.ui:72
-msgid "Change _Status"
-msgstr "_Status ändern"
-
-#: ui/ContactListWindow.vala:670
-msgid "Connected to the network"
-msgstr "Mit dem Netzwerk verbunden"
-
-#: core/ToxSession.vala:720
-#, c-format
-msgid "Connecting to DHT Nodes:\n"
-msgstr "Mit den DHT-Knoten verbunden:\n"
-
-#: ui/ContactListWindow.vala:668
-#, c-format
-msgid "Connection to DHT %s.\n"
-msgstr "Verbindung zum DHT %s.\n"
-
-#: ui/ContactListWindow.vala:907
-#, c-format
-msgid "Contact accepted file sending request\n"
-msgstr "Kontakt hat die Sendeanfrage akzeptiert\n"
-
-#: ui/ContactListWindow.vala:508
-#, c-format
-msgid "Copied Tox ID to clipboard\n"
-msgstr "Tox-ID wurde in die Zwischenablage kopiert\n"
-
-#: ui/ContactListWindow.vala:1135
-#, c-format
-msgid "Could not add friend: %s.\n"
-msgstr "Konnte Freund nicht hinzufügen: %s.\n"
-
-#: ui/ContactListWindow.vala:1123
-msgid "Could not add friend: Invalid ID\n"
-msgstr "Konnte Freund nicht hinzufügen: Ungültige ID\n"
-
-#: core/SqliteTools.vala:40
-#, c-format
-msgid "Could not bind int to %s."
-msgstr "Konnte int nicht auf %s binden."
-
-#: core/SqliteTools.vala:50
-#, c-format
-msgid "Could not bind int64 to %s."
-msgstr "Konnte int64 nicht auf %s binden."
-
-#: core/SqliteTools.vala:60
-#, c-format
-msgid "Could not bind text to %s"
-msgstr "Konnte text nicht auf %s binden."
-
-#: ui/ContactListWindow.vala:447
-#, c-format
-msgid "Could not change user name!\n"
-msgstr "Konnte den Benutzernamen nicht ändern!\n"
-
-#: ui/ContactListWindow.vala:455
-#, c-format
-msgid "Could not change user statusmessage!\n"
-msgstr "Konnte die Statusmeldung nicht ändern!\n"
-
-#: ui/ContactListWindow.vala:1189
-#, c-format
-msgid "Could not create a new groupchat.\n"
-msgstr "Konnte keinen neuen Gruppenchat erstellen.\n"
-
-#: ui/ContactListWindow.vala:725
-#, c-format
-msgid "Could not join groupchat.\n"
-msgstr "Konnte dem Gruppenchat nicht beitreten.\n"
-
-#: ui/ContactListWindow.vala:146
-#, c-format
-msgid "Could not load session data (%s), creating new one.\n"
-msgstr "Konnte die Sitzungsdaten (%s) nicht laden, erstelle neue.\n"
-
-#: ui/ContactListWindow.vala:130
-#, c-format
-msgid "Could not read theme from \"%s\""
-msgstr "Konnte das Thema aus \"%s\" nicht lesen"
-
-#: ui/ContactListWindow.vala:1090
-#, c-format
-msgid "Could not remove %s.\n"
-msgstr "Konnte %s nicht entfernen.\n"
-
-#: ui/ContactListWindow.vala:1068
-#, c-format
-msgid "Could not remove contact %i.\n"
-msgstr "Konnte Kontakt %i nicht entfernen\n"
-
-#: core/ToxSession.vala:352
-#, c-format
-msgid "Could not remove peer [%i] from groupchat #%i (no such peer)\n"
-msgstr ""
-"Konnte Peer [%i] nicht aus Gruppenchat #%i entfernen (Peer nicht vorhanden)\n"
+#: src/ui/add_contact_widget.ui:108
+msgid "Send a friend request"
+msgstr "Sende eine Freundschaftsanfrage"
-#: ui/ContactListWindow.vala:1112
-msgid "Could not resolve ID from DNS record\n"
-msgstr "Konnte ID nicht aus dem DNS-Record ermitteln\n"
+#: src/ui/add_contact_widget.ui:142
+msgid "_ID:"
+msgstr "_ID:"
-#: ui/contact_list.ui:416
-msgid "Create groupchat"
-msgstr "Gruppenchat erstellen"
+#: src/ui/add_contact_widget.ui:159
+msgid "Enter a Tox ID or URI here"
+msgstr "Gib eine Tox-ID oder eine Tox-URI ein"
-#: ui/settings_window.ui:301
-msgid "Default Tox DNS ID suffix:"
-msgstr "Standard-DNS-Suffix für Tox:"
+#: src/ui/create_groupchat_widget.ui:122 src/ui/add_contact_widget.ui:163
+msgid "paste from clipboard"
+msgstr "Zwischenablage einfügen"
-#: ui/FileTransferChatEntry.vala:125 ui/FileTransferChatEntry.vala:129
-msgid "Disconnected"
-msgstr "Getrennt"
+#: src/ui/add_contact_widget.ui:197
+msgid "Enter your friends Tox ID"
+msgstr "Gib die Tox ID deines Freunds / deiner Freundin ein"
-#: ui/ContactListWindow.vala:673
-msgid "Disconnected from the network"
-msgstr "Vom Netz getrennt"
+#: src/ui/friend_request_widget.ui:100 src/ui/add_contact_widget.ui:229
+msgid "_Message:"
+msgstr "_Nachricht:"
-#: ui/UserInfoWindow.vala:86
-msgid "Edit user information"
-msgstr "Benutzerinformationen bearbeiten"
+#: src/ui/add_contact_widget.ui:255
+msgid "Send a custom message to be displayed to the friend you are adding"
+msgstr "Sende eine benutzerdefinierte Mitteilung, die dem Freund / der Freundin, den / die du hinzufügen möchtest, angezeigt wird"
-#: ui/ContactListWindow.vala:899
-#, c-format
-msgid "Ended file transfer for %s to %s\n"
-msgstr "Übermittlung der Datei %s an %s abgeschlossen\n"
+#: src/ui/add_contact_widget.ui:277
+msgid "Send your friend a short message"
+msgstr "Sende deinem Freund / deiner Freundin eine kurze Nachricht"
-#: ui/ContactListWindow.vala:102
-#, c-format
-msgid "Ending session...\n"
-msgstr "Beende Sitzung...\n"
+#: src/ui/add_contact_widget.ui:308
+msgid "Send"
+msgstr "Abschicken"
-#: ui/add_contact_dialog.ui:40
-msgid "Enter a Tox ID here or a Tox URI"
-msgstr "Gib eine Tox-ID oder eine Tox-URI ein"
+#: src/ui/app_menu.ui:28
+msgid "_Preferences"
+msgstr "_Einstellungen"
-#: core/ContactStorage.vala:108
-#, c-format
-msgid "Error creating contacts insert statement: %d: %s\n"
-msgstr ""
-"Fehler bei der Erstellung der Einfügeanweisung auf die Kontakttabelle: %d: "
-"%s\n"
+#: src/ui/app_menu.ui:34
+msgid "About"
+msgstr "_Über"
-#: core/ContactStorage.vala:113
-#, c-format
-msgid "Error creating contacts select statement: %d: %s\n"
-msgstr ""
-"Fehler bei der Erstellung des Selektionsanweisung auf die Kontakttabelle: "
-"%d: %s\n"
+#: src/ui/app_menu.ui:38
+msgid "_Quit"
+msgstr "_Beenden"
-#: core/ContactStorage.vala:103
-#, c-format
-msgid "Error creating contacts table: %s\n"
-msgstr "Fehler bei der Erstellung der Kontakttabelle: %s\n"
+#: src/ui/create_groupchat_widget.ui:121 src/ui/conference_info_widget.ui:61
+msgid "Conference"
+msgstr "Konferenz"
-#: core/DhtNodeStorage.vala:177
-#, c-format
-msgid "Error creating dht nodes insert statement: %d: %s\n"
-msgstr ""
-"Fehler bei der Erstellung der Einfügeanweisung auf die DHT-Knoten-Tabelle: "
-"%d: %s\n"
+#: src/ui/conference_info_widget.ui:127
+msgid "Title:"
+msgstr "Titel:"
-#: core/DhtNodeStorage.vala:182
-#, c-format
-msgid "Error creating dht nodes select statement: %d: %s\n"
-msgstr ""
-"Fehler bei der Erstellung der Selektionsanweisung auf die Kontakttabelle: "
-"%d: %s\n"
-
-#: core/DhtNodeStorage.vala:172
-#, c-format
-msgid "Error creating dht nodes table: %s\n"
-msgstr "Fehler bei der Erstellung der Kontakttabelle: %s\n"
-
-#: core/ToxDns.vala:36
-#, c-format
-msgid "Error creating tox dns regex: %s\n"
-msgstr "Fehler bei der Erstellung des Tox-DNS-Regex: %s\n"
-
-#: core/ToxDns.vala:51
-#, c-format
-msgid "Error creating tox uri regex: %s\n"
-msgstr "Fehler bei der Erstellung des Tox-URI-Regex: %s\n"
-
-#: ui/ConversationTextView.vala:184
-#, c-format
-msgid "Error matching uri regex: %s\n"
-msgstr "Fehler beim Matchen des URI-Regex: %s\n"
-
-#: ui/ConversationWidget.vala:308
-#, c-format
-msgid "Error occured while getting file size: %s"
-msgstr "Fehler beim Ermitteln der Dateigröße: %s"
-
-#: core/ToxSession.vala:111
-#, c-format
-msgid "Error opening database: %s\n"
-msgstr "Feher beim Öffnen der Datenbank: %s\n"
-
-#: core/Settings.vala:112
-#, c-format
-msgid "Error reading configs:%s\n"
-msgstr "Fehler beim Lesen der Konfigurationsdateien:%s\n"
-
-#: core/ToxDns.vala:81
-#, c-format
-msgid "Error resolving name: %s\n"
-msgstr "Fehler bei der Namensauflösung: %s\n"
-
-#: core/MessageLog.vala:135
-#, c-format
-msgid "Error retrieving logs from sqlite database: %s\n"
-msgstr "Fehler beim Holen der Logs von der SQLite-Datenbank: %s\n"
-
-#: core/Settings.vala:99
-#, c-format
-msgid "Error saving configs:%s\n"
-msgstr "Fehler beim Speichern der Konfigurationsdateien: %s\n"
-
-#: core/Tools.vala:123
-#, c-format
-msgid "Error when doing uri markup: %s"
-msgstr "Fehler bei der Erstellung des URI-Markups: %s"
-
-#: ui/ConversationTextView.vala:245
-#, c-format
-msgid "Error when showing uri: %s\n"
-msgstr "Fehler bei der Anzeige der URI: %s\n"
-
-#: ui/ContactListWindow.vala:168
-#, c-format
-msgid "Error while loading icon: %s\n"
-msgstr "Fehler beim Laden des Symbols: %s\n"
-
-#: core/ResourceFactory.vala:126
-#, c-format
-msgid "Error while loading image from \"%s\":%s\n"
-msgstr "Fehler beim Laden der Grafik von \"%s\":%s\n"
-
-#: core/ToxSession.vala:801
-msgid "Error while loading messenger data."
-msgstr "Fehler beim Laden der Messenger-Daten."
-
-#: core/ToxSession.vala:795
-msgid "Error while reading from stream."
-msgstr "Fehler beim Lesen vom Datenstrom."
-
-#: ui/FileTransferChatEntry.vala:171
-#, c-format
-msgid "Error while trying to create file: %s\n"
-msgstr "Fehler bei der Erstellung der Datei: %s\n"
-
-#: ui/ContactListWindow.vala:961
-#, c-format
-msgid "Error while trying to write data to file\n"
-msgstr "Fehler beim Schreiben der Daten in die Datei\n"
-
-#: core/ToxSession.vala:828
-msgid "Error while writing to stream."
-msgstr "Fehler beim Schreiben vom Datenstrom."
-
-#: core/ContactStorage.vala:88
-#, c-format
-msgid "Error writing contact to sqlite database: %s\n"
-msgstr "Fehler beim Schreiben des Kontakts in die SQLite-Datenbank: %s\n"
-
-#: core/MessageLog.vala:118
-#, c-format
-msgid "Error writing message to sqlite database: %s\n"
-msgstr "Fehler beim Schreiben der Mitteilung in die SQLite-Datenbank: %s\n"
-
-#: core/MessageLog.vala:186 core/MessageLog.vala:193
-#, c-format
-msgid "Error: %d: %s\n"
-msgstr "Fehler: %d: %s\n"
-
-#: core/MessageLog.vala:169 core/MessageLog.vala:179
-#: ui/ConversationView.vala:78
-#, c-format
-msgid "Error: %s\n"
-msgstr "Fehler: %s\n"
-
-#: core/ToxSession.vala:788
-#, c-format
-msgid "File \"%d\" does not exist."
-msgstr "Datei \"%d\" existiert nicht."
-
-#: ui/ContactListWindow.vala:929
-#, c-format
-msgid "File transfer finished for file number %u"
-msgstr "Transfer für Datei Nr. %u abgeschlossen"
-
-#: ui/ContactListWindow.vala:925
-#, c-format
-msgid "File transfer was rejected for file number %u"
-msgstr "Transfer wurde für Datei Nr. %u abgelehnt"
-
-#: ui/FileTransferChatEntry.vala:94
-msgid "File was rejected"
-msgstr "Datei wurde abgelehnt"
-
-#: ui/settings_window.ui:236
-msgid "Flash window when a new message arrives"
-msgstr "Flackern, wenn eine neue Mitteilung ankommt"
-
-#: ui/ContactListWindow.vala:614
-#, c-format
-msgid "Friend could not be added.\n"
-msgstr "Freund konnte nicht hinzugefügt werden.\n"
-
-#: core/Tools.vala:138
-msgid "Friend request already sent"
-msgstr "Freundschaftsanfrage bereits gesendet"
-
-#: core/Tools.vala:148
-msgid "Friend request successfully sent"
-msgstr "Freundschaftsanfrage erfolgreich gesendet"
-
-#: ui/ContactListWindow.vala:1142
-#, c-format
-msgid "Friend request successfully sent. Friend added as %i.\n"
-msgstr ""
-"Freundschaftsanfrage erfolgreich gesendet. Freund als %i hinzugefügt.\n"
-
-#: ui/ContactListWindow.vala:771
-#, c-format
-msgid "Group action from unknown contact #%i [%i]\n"
-msgstr "Gruppenaktion von unbekanntem Kontakt #%i [%i]\n"
-
-#: ui/ContactListWindow.vala:708
-#, c-format
-msgid "Group invite from %s with public key %s\n"
-msgstr "Gruppeneinladung von %s mit öffentlichem Schlüssel %s\n"
-
-#: ui/ContactListWindow.vala:742
-#, c-format
-msgid "Group message from unknown contact #%i [%i]\n"
-msgstr "Gruppenmitteilung von unbekanntem Kontakt #%i [%i]\n"
-
-#: core/GroupChat.vala:45
-#, c-format
-msgid "Groupchat #%i"
-msgstr "Gruppenchat #%i"
-
-#: ui/ContactListWindow.vala:896
-#, c-format
-msgid "I/O error while trying to close file stream: %s\n"
-msgstr "E/A-Fehler beim Schließen des Datenstroms: %s\n"
-
-#: ui/ContactListWindow.vala:888
-#, c-format
-msgid "I/O error while trying to read file: %s\n"
-msgstr "E/A-Fehler beim Lesen der Datei: %s\n"
-
-#: ui/AddContactDialog.vala:96
-msgid "ID contains invalid characters"
-msgstr "ID enthält ungültige Zeichen"
-
-#: ui/user_info_window.ui:40
+#: src/ui/conference_info_widget.ui:266 src/ui/user_info_widget.ui:446
+#: src/ui/friend_info_widget.ui:609
+msgid "Apply"
+msgstr "Anwenden"
+
+#: src/ui/conference_info_widget.ui:284
+msgid "Peers"
+msgstr "Mitglieder"
+
+#: src/ui/conference_window.ui:103 src/ui/conversation_window.ui:292
+#: src/ui/user_info_widget.ui:277 src/ui/user_info_widget.ui:278
+msgid "Insert Emoji"
+msgstr "Emoji einfügen"
+
+#: src/ui/contact_list_widget.ui:217
+msgid "Filter contacts by status"
+msgstr "Zeige nur Kontakte mit Status"
+
+#: src/ui/contact_list_widget.ui:223
+msgid "All"
+msgstr "Alle"
+
+#: src/ui/contact_list_widget.ui:331
+msgid "Add a contact"
+msgstr "Kontakt hinzufügen"
+
+#: src/ui/contact_list_widget.ui:381
+msgid "View file transfers"
+msgstr "Zeige Dateiübetragungen"
+
+#: src/ui/conversation_window.ui:37
+msgid "Start a call"
+msgstr "Starte einen Anruf"
+
+#: src/ui/conversation_window.ui:317
+msgid "Insert attachment"
+msgstr "Füge einen Anhang hinzu"
+
+#: src/ui/create_groupchat_widget.ui:102
+msgid "_Title:"
+msgstr "_Titel:"
+
+#: src/ui/create_groupchat_widget.ui:188
+msgid "T_ype:"
+msgstr "T_yp:"
+
+#: src/ui/create_groupchat_widget.ui:282
+msgid "Create"
+msgstr "Erstellen"
+
+#: src/view/FileTransferWidget.vala:39 src/ui/file_transfer_widget.ui:57
+msgid "File transfers"
+msgstr "Dateiübertragungen"
+
+#: src/ui/friend_info_widget.ui:171
+msgid "Remove from your friends list"
+msgstr "Entferne von deiner Kontaktliste"
+
+#: src/ui/user_info_widget.ui:213
+msgid "Username:"
+msgstr "Benutzername:"
+
+#: src/ui/friend_info_widget.ui:222
+msgid "Alias:"
+msgstr "Alias:"
+
+#: src/ui/friend_info_widget.ui:254
+msgid "Set a custom alias to quickly find your friends"
+msgstr "Setze einen Alias um deine Freunde schnell zu finden"
+
+#: src/ui/user_info_widget.ui:319 src/ui/friend_info_widget.ui:520
+msgid "Tox"
+msgstr "Tox"
+
+#: src/ui/user_info_widget.ui:352
msgid "ID:"
msgstr "ID:"
-#: ui/ContactListWindow.vala:86
-#, c-format
-msgid "ID: %s\n"
-msgstr "ID: %s\n"
-
-#: ui/user_info_window.ui:222
-msgid "Icon:"
-msgstr "Symbol:"
-
-#: core/SqliteTools.vala:37 core/SqliteTools.vala:47 core/SqliteTools.vala:57
-#, c-format
-msgid "Index for %s not found."
-msgstr "Index für %s nicht gefunden."
-
-#: ui/conversation_window.ui:290
-msgid "Insert Smiley"
-msgstr "Smiley einfügen"
-
-#: core/ToxDns.vala:113
-#, c-format
-msgid "Invalid record\n"
-msgstr "Ungültiger Eintrag\n"
-
-#: core/ToxDns.vala:64
-#, c-format
-msgid "Invalid tox uri\n"
-msgstr "Ungültige Tox-URI\n"
-
-#: ui/ContactListWindow.vala:728
-#, c-format
-msgid "Joined Groupchat #%i\n"
-msgstr "Gruppenchat #%i beigetreten\n"
-
-#: ui/settings_window.ui:18
-msgid "KB/MB"
-msgstr "KB/MB"
-
-#: ui/settings_window.ui:78
-msgid "Keep history"
-msgstr "Verlauf beibehalten"
-
-#: ui/settings_window.ui:14
-msgid "KiB/MiB"
-msgstr "KiB/MiB"
-
-#: core/Contact.vala:117
-#, c-format
-msgid "Last seen: %s"
-msgstr "Zuletzt gesehen: %s"
+#: src/ui/message_widget.ui:110
+msgid "Message sent ✓"
+msgstr "Nachricht gesendet ✓"
-#: ui/AddContactDialog.vala:53
-#, c-format
-msgid "Loading add contact window failed!\n"
-msgstr "Laden des Kontakt-hinzufügen-Fensters fehlgeschlagen!\n"
+#: src/ui/message_widget.ui:126
+msgid "Message received ✓"
+msgstr "Nachricht empfangen ✓"
-#: ui/ConversationWidget.vala:71 ui/SettingsWindow.vala:32
-#, c-format
-msgid "Loading conversation window failed!\n"
-msgstr "Laden des Unterhaltungsfensters fehlgeschlagen!\n"
+#: src/ui/peer_entry_compact.ui:53 src/ui/peer_entry.ui:77
+msgid "This peer is also in your friends list"
+msgstr "Dieses Mitglied ist auch in deiner Kontaktliste"
-#: ui/FileTransferChatEntry.vala:40
-#, c-format
-msgid "Loading message widget failed!\n"
-msgstr "Laden des Mitteilungs-Widgets fehlgeschlagen!\n"
+#: src/ui/settings_widget.ui:78
+msgid "General"
+msgstr "Generell"
-#: core/Tools.vala:132
-msgid "Message too long"
-msgstr "Mitteilung zu lang"
+#: src/ui/settings_widget.ui:251
+msgid "Appearance"
+msgstr "Erscheinungsbild"
-#: ui/settings_window.ui:337
-msgid "Miscellaneous"
-msgstr "Verschiedenes"
+#: src/ui/settings_widget.ui:296
+msgid "Dark Theme"
+msgstr "Dunkles Thema"
-#: ui/user_info_window.ui:192
-msgid "Name:"
-msgstr "Name:"
+#: src/ui/settings_widget.ui:506
+msgid "Minimize to tray"
+msgstr "Minimiere in Tray"
-#: ui/ContactListWindow.vala:604
-#, c-format
-msgid ""
-"New friend request from '%s'.\n"
-"Do you want to accept?"
-msgstr ""
-"Neue Freundschaftsanfrage von '%s'.\n"
-"Möchtest du annehmen?"
+#: src/ui/settings_widget.ui:603
+msgid "Privacy"
+msgstr "Privatsphäre"
+
+#: src/ui/settings_widget.ui:647
+msgid "Send typing notifications"
+msgstr "Sende Schreibbenachrichtigungen"
+
+#: src/ui/settings_widget.ui:660
+msgid "Show others when I am typing"
+msgstr "Zeige anderen wenn du tippst"
+
+#: src/ui/settings_widget.ui:744
+msgid "History"
+msgstr "Verlauf"
+
+#: src/ui/settings_widget.ui:879
+msgid "days"
+msgstr "Tagen"
-#: ui/AddContactDialog.vala:90
-msgid "No ID given"
-msgstr "Keine ID angegeben"
+#: src/ui/settings_widget.ui:910
+msgid "Delete all previous conversations"
+msgstr "Lösche alle bisherigen Konversationen"
-#: core/Tools.vala:134
-msgid "No message included"
-msgstr "Keine Mitteilung enthalten"
+#: src/ui/settings_widget.ui:1328
+msgid "Update bootstrap nodes"
+msgstr "Erneuere bootstrap Knoten"
-#: core/ToxDns.vala:103
-#, c-format
-msgid "No pin privided, aborting...\n"
-msgstr "Keine PIN angegeben, Abbruch ...\n"
+#: src/ui/user_info_widget.ui:394
+msgid "Copy to clipboard"
+msgstr "Kopiere in die Zwischenablage"
-#: ui/contact_list.ui:118
-msgid "O_ffline"
-msgstr "O_ffline"
+#: src/ui/welcome_widget.ui:62
+msgid "A new kind of instant messaging"
+msgstr "Eine neue Art des Instant Messagings"
-#: core/Contact.vala:98 core/Contact.vala:108 core/ToxSession.vala:37
+#: src/ui/welcome_widget.ui:78
+msgid "Chat with your friends and family without anyone else listening in."
+msgstr "Plaudere mit deinen Freunden und Familie ohne dass jemand mithört."
+
+#: src/ui/welcome_widget.ui:131
+msgid "Learn more"
+msgstr "Erfahre mehr"
+
+#: src/core/Message.vala:79 src/viewmodel/MessageViewModel.vala:86
+#: src/tox/ConferenceMessage.vala:56
+msgid "me"
+msgstr "Ich"
+
+#: src/ui/user_info_widget.ui:110
+msgid "Choose an avatar"
+msgstr "Wähle einen Avatar aus"
+
+#: src/ui/friend_request_widget.ui:168
+msgid "Reject request"
+msgstr "Anfrage ablehnen"
+
+#: src/ui/friend_request_widget.ui:192
+msgid "Accept request"
+msgstr "Anfrage annehmen"
+
+#: src/core/NotificationListener.vala:76
+msgid "New file from %s"
+msgstr "Neue Datei von %s"
+
+#: src/viewmodel/ContactListEntryViewModel.vala:58
+msgid "New Message!"
+msgstr "Neue Nachricht!"
+
+#: src/viewmodel/ContactListEntryViewModel.vala:64
msgid "Offline"
msgstr "Offline"
-#: core/GroupChatContact.vala:32 core/ToxSession.vala:31
-#: ui/ContactListWindow.vala:208
+#: src/viewmodel/ContactListEntryViewModel.vala:72
+#: src/ui/user_status_menu.ui:34
+msgid "Away"
+msgstr "Abwesend"
+
+#: src/viewmodel/ContactListEntryViewModel.vala:74
+#: src/ui/user_status_menu.ui:40
+msgid "Busy"
+msgstr "Beschäftigt"
+
+#: src/viewmodel/ContactListEntryViewModel.vala:76
+#: src/ui/user_status_menu.ui:28
msgid "Online"
msgstr "Online"
-#: ui/contact_list.ui:449
-msgid "Open preferences"
-msgstr "Einstellungen öffnen"
+#: src/core/TimeStamp.vala:40
+msgid "Today at %s"
+msgstr "Heute um %s"
-#: core/Tools.vala:146
-msgid "Out of memory"
-msgstr "Nicht genügend Speicher"
+#: src/core/TimeStamp.vala:44
+msgid "Yesterday at %s"
+msgstr "Gestern um %s"
-#: ui/FileTransferChatEntry.vala:104
-msgid "Paused"
-msgstr "In Pause"
+#: src/tox/Conference.vala:44
+msgid "Unnamed conference %u"
+msgstr "Unbenannte Konferenz %u"
-#: ui/PinDialog.vala:37
-#, c-format
-msgid ""
-"Please insert PIN for \n"
-"%s"
-msgstr ""
-"Bitte PIN eingeben für \n"
-"%s"
+#: src/tox/ToxSession.vala:657
+msgid "Address must consist of 76 hexadecimal characters"
+msgstr "Addresse muss aus 76 hexadezimalen Zeichen bestehen"
-#: ui/PinDialog.vala:49
-msgid "Please insert PIN..."
-msgstr "Bitte PIN eingeben..."
+#: src/view/ConversationWindow.vala:227 src/view/FileTransferEntry.vala:86
+msgid "_Cancel"
+msgstr "Abbre_chen"
-#: ui/add_contact_dialog.ui:6
-msgid "Please let me add you to my contact list."
-msgstr "Bitte lass mich dich meiner Kontaktliste hinzufügen."
+#: src/view/ConversationWindow.vala:226
+msgid "_Open"
+msgstr "Öffnen"
-#: ui/settings_window.ui:221
-msgid "Privacy"
-msgstr "Privatsphäre"
+#: src/view/FileTransferEntry.vala:85
+msgid "_Save"
+msgstr "_Speichern"
-#: ui/ContactListWindow.vala:869
-#, c-format
-msgid "Read incorrect number of bytes from file\n"
-msgstr "Fehlerhafte Anzahl Bytes von Datei gelesen\n"
+#: src/ui/file_transfer_widget.ui:140
+msgid "No file transfers yet …"
+msgstr "Keine Dateiübertragungen bisher …"
-#: ui/FileTransferChatEntry.vala:113
-msgid "Receiving failed"
-msgstr "Empfang fehlgeschlagen"
+#: src/ui/file_transfer_entry.ui:56 src/ui/file_transfer_entry_inline.ui:62
+msgid "Remove transfer"
+msgstr "Lösche Dateiübertragung"
-#: ui/ContactListWindow.vala:1114
-msgid "Resolving ID failed"
-msgstr "ID konnte nicht aufgelöst werden"
+#: src/ui/file_transfer_entry.ui:124 src/ui/file_transfer_entry_inline.ui:130
+msgid "Open file"
+msgstr "Öffne Datei"
-#: ui/ContactListWindow.vala:427
-#, c-format
-msgid "Retrieved contact %s from savefile.\n"
-msgstr "Kontakt %s wurde aus der Sicherungsdatei wiederhergestellt.\n"
+#: src/ui/file_transfer_entry.ui:148 src/ui/file_transfer_entry_inline.ui:154
+msgid "Start transfer"
+msgstr "Übertragung starten"
-#: Main.vala:50
-#, c-format
-msgid "Run '%s --help' to see a full list of available command line options.\n"
-msgstr ""
-"Führe '%s --help' aus, um eine vollständige Liste der verfügbaren "
-"Kommandozeilenoptionen zu sehen.\n"
-
-#: core/MessageLog.vala:86
-#, c-format
-msgid "SQLite database closed.\n"
-msgstr "SQLite-Datenbank geschlossen.\n"
-
-#: core/MessageLog.vala:82
-#, c-format
-msgid "SQLite database created.\n"
-msgstr "SQLite-Datenbank erstellt.\n"
-
-#: ui/FileTransferChatEntry.vala:158
-msgid "Save"
-msgstr "Speichern"
-
-#: ui/FileTransferChatEntry.vala:155
-msgid "Save file"
-msgstr "Datei speichern"
-
-#: ui/ContactListWindow.vala:120
-#, c-format
-msgid "Saving session file failed: %s\n"
-msgstr "Speichern der Sitzungsdatei fehlgeschlagen: %s\n"
-
-#: ui/FileTransferChatEntry.vala:165
-#, c-format
-msgid "Saving to: %s\n"
-msgstr "Speichere nach: %s\n"
-
-#: ui/ContactListWindow.vala:116
-#, c-format
-msgid "Saving tox session data\n"
-msgstr "Speichere Tox-Sitzungsdaten\n"
-
-#: ui/ConversationWidget.vala:282
-msgid "Select"
-msgstr "Auswählen"
-
-#: ui/ConversationWidget.vala:279
-msgid "Select a file to send"
-msgstr "Wähle eine Datei zum Versenden aus"
-
-#: ui/add_contact_dialog.ui:113
-msgid "Send a custom message to be displayed to the friend you are adding"
-msgstr ""
-"Sende eine benutzerdefinierte Mitteilung, die dem Freund, den du hinzufügen "
-"möchtest, angezeigt wird."
+#: src/ui/file_transfer_entry.ui:169 src/ui/file_transfer_entry_inline.ui:175
+msgid "Pause transfer"
+msgstr "Übertragung pausieren"
+
+#: src/ui/file_transfer_entry.ui:190 src/ui/file_transfer_entry_inline.ui:196
+msgid "Stop transfer"
+msgstr "Übertragung stoppen"
+
+#: src/ui/create_groupchat_widget.ui:212
+msgid "Text"
+msgstr "Text"
+
+#: src/ui/create_groupchat_widget.ui:228
+msgid "Speech"
+msgstr "Sprache"
+
+#: src/ui/peer_entry_compact.ui:39 src/ui/peer_entry.ui:90
+msgid "That's you"
+msgstr "Das bist du"
+
+#: src/ui/welcome_widget.ui:178
+msgid "Get involved"
+msgstr "Mitmachen"
+
+#: src/ui/settings_widget.ui:161
+msgid "Proxy"
+msgstr "Proxy"
+
+#: src/ui/settings_widget.ui:309
+msgid "Use a dark variant of the theme"
+msgstr "Benutze eine dunkle Variante des Themas"
-#: ui/conversation_window.ui:308
-msgid "Send file"
-msgstr "Datei senden"
+#: src/ui/settings_widget.ui:366
+msgid "Animations"
+msgstr "Animationen"
-#: ui/conversation_window.ui:341
-msgid "Send message"
-msgstr "Nachricht senden"
+#: src/ui/settings_widget.ui:379
+msgid "Enable animated transitions"
+msgstr "Aktiviere animierte Übergänge"
-#: ui/FileTransferChatEntry.vala:107
-msgid "Sending failed"
-msgstr "Senden fehlgeschlagen"
+#: src/ui/settings_widget.ui:436
+msgid "Notifications"
+msgstr "Benachrichtigungen"
-#: ui/ContactListWindow.vala:111
-#, c-format
-msgid "Session ended gracefully.\n"
-msgstr "Sitzung dankbar beendet.\n"
+#: src/ui/settings_widget.ui:449
+msgid "Show notifications for unread messages"
+msgstr "Zeige Benachrichtigungen für ungelesene Nachrichten"
-#: ui/add_contact_dialog.ui:67
-msgid "Set a custom nickname for the friend you are about to add"
-msgstr "Gib deinem Freund einen Spitznamen"
+#: src/ui/settings_widget.ui:519
+msgid "Minimize app to system tray on close"
+msgstr "Minimiere app in das Systemtray anstatt zu schließen"
-#: core/Tools.vala:144
-msgid "Set new nospam"
-msgstr "Neuen NoSPAM-Wert setzen"
+#: src/ui/settings_widget.ui:809
+msgid "Keep forever"
+msgstr "Behalte für immer"
-#: ui/settings_window.ui:30
+#: src/ui/settings_widget.ui:846
+msgid "Remove older than"
+msgstr "Lösche älter als"
+
+#: src/ui/settings_widget.ui:1004
+msgid "Connection"
+msgstr "Verbindung"
+
+#: src/ui/settings_widget.ui:1047
+msgid "UDP"
+msgstr "UDP"
+
+#: src/ui/settings_widget.ui:1117
+msgid "IPv6"
+msgstr "IPv6"
+
+#: src/ui/settings_widget.ui:1130
+msgid "Allow both IPv4 and IPv6 communication"
+msgstr "Erlaube IPv4 und IPv6 Verbindungen"
+
+#: src/ui/settings_widget.ui:1187
+msgid "Local discovery"
+msgstr "Lokale Erkennung"
+
+#: src/ui/settings_widget.ui:1200
+msgid "Look for peers on the local network"
+msgstr "Suche nach Mitgliedern im lokalen Netzwerk"
+
+#: src/ui/settings_widget.ui:1257
+msgid "Hole punching"
+msgstr "Hole punching"
+
+#: src/ui/settings_widget.ui:1270
+msgid "Enable UDP hole punching"
+msgstr "Aktiviere UDP hole punching"
+
+#: src/ui/settings_widget.ui:1364
+msgid "Bootstrap nodes"
+msgstr "Bootstrap Knoten"
+
+#: src/ui/settings_widget.ui:1500
+msgid "Proxy"
+msgstr "Proxy"
+
+#: src/ui/settings_widget.ui:1567
+msgid "System settings"
+msgstr "Systemeinstellungen"
+
+#: src/ui/settings_widget.ui:1580
+msgid "Use your systems proxy settings"
+msgstr "Benutze die Proxy Einstellungen deines Systems"
+
+#: src/ui/settings_widget.ui:1634
+msgid "Manual settings"
+msgstr "Manuelle Einstellung"
+
+#: src/ui/settings_widget.ui:1647
+msgid "Use custom proxy settings"
+msgstr "Setze Benutzerdefinierte Proxy Einstellungen"
+
+#: src/ui/settings_widget.ui:1688
+msgid "Host"
+msgstr "Host"
+
+#: src/ui/settings_widget.ui:1728
+msgid "Set a SOCKS5 proxy to connect to"
+msgstr "Setze einen SOCKS5 Proxyserver"
+
+#: src/ui/friend_info_widget.ui:242
+msgid "Reset alias"
+msgstr "Alias zurücksetzen"
+
+#: src/ui/friend_info_widget.ui:364
+msgid "Auto accept conference invites"
+msgstr "Konferenzeinladungen automatisch akzeptieren"
+
+#: src/ui/friend_info_widget.ui:411
+msgid "Auto accept file transfers"
+msgstr "Dateiübertragungen automatisch akzeptieren"
+
+#: src/ui/friend_info_widget.ui:455
+msgid "Save files to"
+msgstr "Speichere Dateien nach"
+
+#: src/viewmodel/ContactListViewModel.vala:102
+msgid "New conference…"
+msgstr "Neue Konferenz…"
+
+#: src/viewmodel/ContactListViewModel.vala:115
+msgid "Invite to conference"
+msgstr "Lade in Konferenz ein"
+
+#: src/viewmodel/ContactListViewModel.vala:118 src/ui/conference_window.ui:137
+#: src/ui/conversation_window.ui:86
+msgid "Show details"
+msgstr "Zeige Details"
+
+#: src/viewmodel/ContactListViewModel.vala:140
+msgid "%u new friend request"
+msgid_plural "%u new friend requests"
+msgstr[0] "%u neue Freundschaftsanfrage"
+msgstr[1] "%u neue Freundschaftsanfragen"
+
+#: src/viewmodel/ContactListViewModel.vala:148
+msgid "%u new conference invite"
+msgid_plural "%u new conference invites"
+msgstr[0] "%u neue Konferenzeinladung"
+msgstr[1] "%u neue Konferenzeinladungen"
+
+#: src/core/TimeStamp.vala:26
+msgid "Just now"
+msgstr "Gerade eben"
+
+#: src/core/TimeStamp.vala:31
+msgid "%u minute ago"
+msgid_plural "%u minutes ago"
+msgstr[0] "vor %u Minute"
+msgstr[1] "vor %u Minuten"
+
+#: src/core/TimeStamp.vala:36
+msgid "%u hour ago"
+msgid_plural "%u hours ago"
+msgstr[0] "vor %u Stunde"
+msgstr[1] "vor %u Stunden"
+
+#: src/ui/create_groupchat_widget.ui:68 src/ui/contact_list_widget.ui:356
+msgid "Create a conference"
+msgstr "Erstelle eine Konferenz"
+
+#: src/ui/create_groupchat_widget.ui:156
+msgid "Name the conference (optional)"
+msgstr "Gib der Konferenz einen Namen (optional)"
+
+#: src/ui/create_groupchat_widget.ui:252
+msgid "Select a conference type"
+msgstr "Wähle die Art der Konferenz"
+
+#: src/ui/create_groupchat_widget.ui:299
+msgid "New conference"
+msgstr "Neue Konferenz"
+
+#: src/ui/create_groupchat_widget.ui:312 src/ui/create_groupchat_widget.ui:346
+msgid "Conference invites"
+msgstr "Konferenzeinladungen"
+
+#: src/ui/create_groupchat_widget.ui:408
+msgid "No new conference invites"
+msgstr "Keine neuen Konferenzeinladungen"
+
+#: src/ui/conversation_window.ui:62
+msgid "Start a video call"
+msgstr "Starte einen Videoanruf"
+
+#: src/ui/friend_request_widget.ui:66
+msgid "_Public key:"
+msgstr "Öffentlicher Schlüssel:"
+
+#: src/ui/conference_info_widget.ui:78
+msgid "Leave Conference"
+msgstr "Verlasse Konferenz"
+
+#: src/ui/conference_info_widget.ui:196 src/ui/friend_info_widget.ui:291
+msgid "Show notifications"
+msgstr "Zeige Benachrichtigungen"
+
+#: src/ui/conference_info_widget.ui:234 src/ui/friend_info_widget.ui:330
+msgid "Notifications have been globally disabled"
+msgstr "Benachrichtigungen sind global deaktiviert"
+
+#: src/ui/conference_invite_entry.ui:65
+msgid "Invite from:"
+msgstr "Einladung von:"
+
+#: src/ui/conference_invite_entry.ui:109
+msgid "Accept invite"
+msgstr "Einladung annehmen"
+
+#: src/ui/conference_invite_entry.ui:133
+msgid "Reject invite"
+msgstr "Einladung ablehnen"
+
+#: src/ui/add_contact_widget.ui:52
+msgid "No new friend requests"
+msgstr "Keine neuen Freundschaftsanfragen"
+
+#: src/ui/contact_list_widget.ui:56 src/ui/add_contact_widget.ui:325
+msgid "Add a friend"
+msgstr "Füge einen Freund hinzu"
+
+#: src/ui/add_contact_widget.ui:338 src/ui/add_contact_widget.ui:372
+msgid "Friend requests"
+msgstr "Freundschaftsanfragen"
+
+#: src/ui/user_info_widget.ui:258
+msgid "Status message:"
+msgstr "Statusmeldung:"
+
+#: src/ui/settings_widget.ui:1060
+msgid "Use UDP communication when available"
+msgstr "Benutze wenn möglich UDP-Verbindungen"
+
+#: src/view/WelcomeWidget.vala:39
+msgid "A new kind of instant messaging"
+msgstr "Eine neue Art des Instant Messagings"
+
+#: src/view/SettingsWidget.vala:69
msgid "Settings"
msgstr "Einstellungen"
-#: core/Settings.vala:102
-#, c-format
-msgid "Settings saved.\n"
-msgstr "Einstellungen gespeichert.\n"
+#: src/ui/conference_window.ui:216 src/ui/conversation_window.ui:129
+msgid "No messages yet..."
+msgstr "Keine Nachrichten bisher..."
-#: ui/settings_window.ui:186
-msgid "Show _others when I am typing"
-msgstr "A_nderen anzeigen, wenn du tippst"
+#: src/ui/contact_list_widget.ui:406
+msgid "Open settings"
+msgstr "Öffne Einstellungen"
-#: ui/settings_window.ui:258
-msgid "Show filesize in"
-msgstr "Dateigröße anzeigen in"
+#: src/ui/contact_list_widget.ui:448
+msgid "Edit your profile"
+msgstr "Bearbeite dein Profil"
-#: ui/settings_window.ui:202
-msgid "Show me when others are typing"
-msgstr "Anzeigen, wenn andere tippen"
+#: src/ui/contact_list_widget.ui:476
+msgid "Change your status"
+msgstr "Ändere deinen Status"
-#: Main.vala:70
-#, c-format
-msgid "Starting in offline mode\n"
-msgstr "Im Offline-Modus starten\n"
+#: src/ui/friend_info_widget.ui:554
+msgid "Public key:"
+msgstr "Öffentlicher Schlüssel:"
-#: ui/user_info_window.ui:178
-msgid "Status message:"
-msgstr "Statusmitteilung:"
+#: src/view/ConversationWindow.vala:223
+msgid "Choose a file to send"
+msgstr "Wähle eine Datei zum Senden aus"
-#: ui/ContactListWindow.vala:408
-#, c-format
-msgid "Theme refreshed\n"
-msgstr "Design neu geladen\n"
+#: src/view/UserInfoWidget.vala:56
+msgid "Images"
+msgstr "Bilder"
-#: ui/Client.vala:116
-msgid "There is currently no help available"
-msgstr "Es ist zurzeit keine Hilfe verfügbar"
+#: src/ui/user_info_widget.ui:62
+msgid "Reset"
+msgstr "Zurücksetzen"
-#: core/ResourceFactory.vala:77
-msgid "Tox User"
-msgstr "Tox-Benutzer"
-
-#: core/ResourceFactory.vala:78
-#, c-format
-msgid "Toxing on Venom v.%s"
-msgstr "Toxen mit Venom v.%s"
-
-#: ui/ContactListWindow.vala:826
-#, c-format
-msgid "Trying to send unknown file"
-msgstr "Versuche, unbekannte Datei zu senden"
-
-#: ui/MessageTextView.vala:27
-msgid "Type your message here..."
-msgstr "Gib hier deine Mitteilung ein ..."
-
-#: core/Tools.vala:140
-msgid "Unknown error"
-msgstr "Unbekannter Fehler"
-
-#: ui/ContactListWindow.vala:890
-#, c-format
-msgid "Unknown error while trying to read file: %s\n"
-msgstr "Unbekannter Fehler beim Lesen der Datei %s\n"
-
-#: Main.vala:65
-#, c-format
-msgid "Using Gtk.TextView to display messages\n"
-msgstr "Verwende Gtk.TextView, um Mitteilungen anzuzeigen\n"
-
-#: Main.vala:60
-#, c-format
-msgid "Using data file \"%s\"\n"
-msgstr "Verwende Datendatei \"%s\"\n"
-
-#: ui/AddContactDialog.vala:100
-msgid "Valid ID size"
-msgstr "Gültige ID-Größe"
-
-#: ui/ContactListWindow.vala:461
-#, c-format
-msgid "Venom (%s)"
-msgstr "Venom (%s)"
-
-#: ui/ConversationTextView.vala:139
-#, c-format
-msgid "[%s] "
-msgstr "[%s] "
-
-#: ui/ContactListWindow.vala:638
-#, c-format
-msgid "[ac] %i:%s\n"
-msgstr "[ac] %i:%s\n"
-
-#: ui/ContactListWindow.vala:598
-#, c-format
-msgid "[fr] %s:%s\n"
-msgstr "[fr] %s:%s\n"
-
-#: ui/ContactListWindow.vala:763
-#, c-format
-msgid "[ga] %s [%i]@%i: %s\n"
-msgstr "[ga] %s [%i]@%i: %s\n"
-
-#: ui/ContactListWindow.vala:734
-#, c-format
-msgid "[gm] %s [%i]@%i: %s\n"
-msgstr "[gm] %s [%i]@%i: %s\n"
-
-#: ui/ContactListWindow.vala:660
-#, c-format
-msgid "[rr] %s:%u\n"
-msgstr "[rr] %s:%u\n"
-
-#: ui/ContactListWindow.vala:656
-#, c-format
-msgid "[us] %s:%i\n"
-msgstr "[us] %s:%i\n"
-
-#: ui/contact_list.ui:96
-msgid "_Away"
-msgstr "_Abwesend"
-
-#: ui/user_info_window.ui:254
-msgid "_Browse..."
-msgstr "_Durchsuchen..."
-
-#: ui/contact_list.ui:107
-msgid "_Busy"
-msgstr "_Beschäftigt"
-
-#: ui/contact_list.ui:61
-msgid "_Copy ID to clipboard"
-msgstr "Tox-ID in die Zwis_chenablage kopieren"
-
-#: ui/contact_list.ui:50
-msgid "_Edit user"
-msgstr "_Benutzer bearbeiten"
-
-#: ui/add_contact_dialog.ui:94
-msgid "_Message (optional):"
-msgstr "_Mitteilung (optional):"
-
-#: ui/add_contact_dialog.ui:54
-msgid "_Nickname (optional):"
-msgstr "_Spitzname (optional):"
-
-#: ui/contact_list.ui:85
-msgid "_Online"
-msgstr "_Online"
-
-#: ui/add_contact_dialog.ui:27
-msgid "_Tox ID:"
-msgstr "_Tox-ID:"
-
-#: ui/contact_list.ui:278
-msgid "connecting..."
-msgstr "verbinden ..."
-
-#: ui/settings_window.ui:160
-msgid "days"
-msgstr "Tagen"
+#: src/ui/user_info_widget.ui:87
+msgid "Take a picture"
+msgstr "Nimm ein Bild auf"
+
+#: src/ui/user_info_widget.ui:109
+msgid "Choose a file"
+msgstr "Wähle eine Datei"
+
+#: src/ui/conference_window.ui:179
+msgid "No one here..."
+msgstr "Niemand hier..."
+
+#: src/ui/conference_window.ui:280
+msgid "Show peers"
+msgstr "Zeige Mitglieder"
+
+#: src/undo/TextBufferUndoBinding.vala:169
+msgid "_Redo"
+msgstr "Wiede_rholen"
+
+#: src/undo/TextBufferUndoBinding.vala:174
+msgid "_Undo"
+msgstr "R_ückgängig"
+
+#: src/viewmodel/FriendInfoViewModel.vala:65
+msgid "Online right now"
+msgstr "Ist gerade online"
+
+#: src/viewmodel/FriendInfoViewModel.vala:67
+msgid "Never seen online"
+msgstr "War noch nie online"
+
+#: src/viewmodel/FriendInfoViewModel.vala:69
+msgid "Last seen: %s"
+msgstr "Zuletzt gesehen: %s"
+
+#: src/view/ConversationWindow.vala:120
+msgid "%s is typing…"
+msgstr "%s tippt gerade …"
+
+#: src/ui/conversation_window.ui:155
+msgid "Attach screenshot…"
+msgstr "Screenshot anhängen…"
+
+#: src/ui/conversation_window.ui:180
+msgid "Attach file…"
+msgstr "Datei anhängen…"
+
+#: src/view/AboutDialog.vala:54 data/chat.tox.venom.desktop.in:4
+msgid "A modern Tox client for the Linux desktop"
+msgstr "Ein moderner Tox Client für den Linux Desktop"
+
+#: src/view/AboutDialog.vala:55
+msgid "Copyright © 2013-2018 Venom authors and contributors"
+msgstr "Copyright © 2013-2018 Venom Authoren und Mitwirkende"
+
+#: data/chat.tox.venom.desktop.in:3
+msgid "Venom"
+msgstr "Venom"
+
+#: data/chat.tox.venom.desktop.in:5
+msgid "tox;instant messaging;video chat;"
+msgstr "tox;instant messaging;video chat;"
+
+#: data/chat.tox.venom.desktop.in:7
+msgid "chat.tox.venom-symbolic"
+msgstr "chat.tox.venom-symbolic"
-#: ui/settings_window.ui:127
-msgid "delete after"
-msgstr "Löschen nach"
-
-#: Main.vala:49
-#, c-format
-msgid "error: %s\n"
-msgstr "Fehler: %s\n"
-
-#: ui/ContactListWindow.vala:668
-msgid "established"
-msgstr "aufgebaut"
-
-#: ui/ContactListWindow.vala:569
-#, c-format
-msgid "failed to send file %s to %s"
-msgstr "Senden der Datei %s an %s fehlgeschlagen"
-
-#: ui/ContactListWindow.vala:1077
-#, c-format
-msgid "groupchat #%i"
-msgstr "Gruppenchat #%i"
-
-#: ui/settings_window.ui:104
-msgid "indefinitely"
-msgstr "unbegrenzt"
-
-#: ui/ContactListWindow.vala:668
-msgid "lost"
-msgstr "verloren"
-
-#: core/GroupChat.vala:56
-msgid "no one connected"
-msgstr "niemand verbunden"
-
-#: ui/ContactListWindow.vala:663
-msgid "offline"
-msgstr "offline"
-
-#: ui/ContactListWindow.vala:663
-msgid "online"
-msgstr "online"
-
-#: ui/ContactListWindow.vala:798
-#, c-format
-msgid "received file send request friend: %i filenumber: %i filename: %s \n"
-msgstr "Sendeanfrage erhalten; Freund: %i; Dateinummer: %i; Dateiname: %s \n"
-
-#: ui/ContactListWindow.vala:562
-#, c-format
-msgid "sending file %s to %s\n"
-msgstr "Sende Datei %s an %s\n"
-
-#: ui/ContactListWindow.vala:1129
-#, c-format
-msgid "setting alias: %s\n"
-msgstr "Setze Alias: %s\n"
-
-#: core/ToxDns.vala:95
-#, c-format
-msgid "tox 1 ID found: %s\n"
-msgstr "Tox-1-ID gefunden: %s\n"
-
-#: core/ToxDns.vala:100
-#, c-format
-msgid "tox 2 ID found: %s %s\n"
-msgstr "Tox-2-ID gefunden: %s %s\n"
-
-#: ui/AboutDialog.vala:46
-msgid "translator-credits"
-msgstr "Spixi "
diff --git a/po/es.po b/po/es.po
index 7bcc32c..38d6591 100644
--- a/po/es.po
+++ b/po/es.po
@@ -1,1024 +1,639 @@
-# SOME DESCRIPTIVE TITLE.
-# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
-# This file is distributed under the same license as the PACKAGE package.
-# FIRST AUTHOR , YEAR.
-#
msgid ""
msgstr ""
-"Project-Id-Version: Venom\n"
-"Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2014-06-17 21:05+0200\n"
-"PO-Revision-Date: 2014-09-19 20:11-0000\n"
-"Last-Translator: oxichem \n"
-"Language-Team: oxichem \n"
-"Language: es_419\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
-"X-Generator: Poedit 1.6.9\n"
+"X-Generator: POEditor.com\n"
+"Project-Id-Version: Venom\n"
+"Language: es\n"
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
-#: core/ToxSession.vala:725
-#, c-format
-msgid " %s\n"
-msgstr " %s\n"
-
-#: core/DhtNode.vala:47
-msgid " (ipv6)"
-msgstr " (ipv6)"
-
-#: ui/ContactListWindow.vala:627
-#, c-format
-msgid "%F"
-msgstr "%F"
-
-#: core/Message.vala:47
-msgid "%R:%S"
-msgstr "%R:%S"
-
-#: core/GroupChat.vala:52
-#, c-format
-msgid "%i people connected"
-msgstr "%i personas conectadas"
-
-#: core/GroupChat.vala:54
-#, c-format
-msgid "%i person connected"
-msgstr "%i persona conectada"
-
-#: core/Contact.vala:69 core/Contact.vala:83
-#, c-format
-msgid "%s (%s)"
-msgstr "%s (%s)"
-
-#: ui/ContactListWindow.vala:648
-#, c-format
-msgid "%s changed his name to %s\n"
-msgstr "%s cambió su nombre a %s\n"
-
-#: ui/ContactListWindow.vala:652
-#, c-format
-msgid "%s changed his status to %s\n"
-msgstr "%s cambió su estado a %s\n"
-
-#: ui/ContactListWindow.vala:663
-#, c-format
-msgid "%s is now %s.\n"
-msgstr "%s es ahora %s.\n"
-
-#: ui/ConversationWidget.vala:60
-#, c-format
-msgid "%s is typing..."
-msgstr "%s está escribiendo..."
-
-#: ui/ContactListWindow.vala:131
-#, c-format
-msgid "%s: %s\n"
-msgstr "%s: %s\n"
-
-#: core/DhtNode.vala:47
-#, c-format
-msgid "%s:%u%s %s"
-msgstr "%s:%u%s %s"
-
-#: ui/ContactListWindow.vala:714
-#, c-format
-msgid "'%s' has invited you to a groupchat, do you want to accept?"
-msgstr "'%s' te ha invitado a un chat grupal. ¿Quiere aceptar?"
-
-#: ui/ContactListWindow.vala:577
-#, c-format
-msgid "* %s"
-msgstr "* %s"
-
-#: ui/ContactListWindow.vala:627
-#, c-format
-msgid "<%i>"
-msgstr "<%i>"
-
-#: ui/ContactListWindow.vala:627
-#, c-format
-msgid "<%s> %s:%s\n"
-msgstr "<%s> %s:%s\n"
-
-#: ui/ConversationWidget.vala:51 ui/GroupConversationWidget.vala:47
-#, c-format
-msgid "%s"
-msgstr "%s"
-
-#: ui/user_info_window.ui:119
-msgid "Tox"
-msgstr "Tox"
-
-#: ui/user_info_window.ui:282
-msgid "User"
-msgstr "Usuario"
-
-#: core/Contact.vala:72 core/Contact.vala:86 ui/ConversationView.vala:55
-#, c-format
-msgid "%s"
-msgstr "%s"
-
-#: core/Message.vala:152 core/Message.vala:191
-msgid ""
-msgstr ""
-
-#: ui/AddContactDialog.vala:76
-msgid "Add contact"
-msgstr "Añadir contacto"
-
-#: ui/ContactListWindow.vala:617
-#, c-format
-msgid "Added new friend #%i\n"
-msgstr "Añadido nuevo amigo #%i\n"
-
-#: ui/ContactListWindow.vala:1125 ui/ContactListWindow.vala:1137
-msgid "Adding Friend failed"
-msgstr "Error al intentar añadir al contacto"
-
-#: ui/ContactListWindow.vala:210
+#: src/core/Application.vala:32
+msgid "Set level of messages to log"
+msgstr "Establecer el nivel de mensajes para iniciar sesión"
+
+#: src/core/Application.vala:32
+msgid ""
+msgstr ""
+
+#: src/core/Application.vala:33
+msgid "Display version number"
+msgstr "Mostrar número de versión"
+
+#: src/core/NotificationListener.vala:55
+msgid "New message from %s"
+msgstr "Nuevo mensaje de %s"
+
+#: src/core/R.vala:70
+msgid "Tox User"
+msgstr "Usuario de Tox"
+
+#: src/tox/Conference.vala:47
+msgid "%u Peers online"
+msgstr "%u Pares en línea"
+
+#: src/view/AboutDialog.vala:53
+msgid "Packagers"
+msgstr "Envasadores"
+
+#: src/view/AboutDialog.vala:58
+msgid "translator-credits"
+msgstr "oxichem"
+
+#: src/view/AboutDialog.vala:61
+msgid "Visit us on Github"
+msgstr "Visítanos en Github"
+
+#: src/ui/add_contact_widget.ui:43
+msgid "Please let me add you to my contact list. 😁"
+msgstr ""
+
+#: src/ui/add_contact_widget.ui:99
+msgid "Send a friend request"
+msgstr "Envía un solicitud de amistad"
+
+#: src/ui/add_contact_widget.ui:133
+msgid "_ID:"
+msgstr ""
+
+#: src/ui/add_contact_widget.ui:150
+msgid "Enter a Tox ID or URI here"
+msgstr ""
+
+#: src/ui/create_groupchat_widget.ui:113 src/ui/add_contact_widget.ui:154
+msgid "paste from clipboard"
+msgstr ""
+
+#: src/ui/add_contact_widget.ui:188
+msgid "Enter your friends Tox ID"
+msgstr "Introduce la ID de Tox de tus amigos"
+
+#: src/ui/friend_request_widget.ui:78 src/ui/add_contact_widget.ui:220
+#, fuzzy
+msgid "_Message:"
+msgstr "_Mensaje (opcional):"
+
+#: src/ui/add_contact_widget.ui:246
+msgid "Send a custom message to be displayed to the friend you are adding"
+msgstr "Envíe un mensaje personalizado para el contacto que está agregando"
+
+#: src/ui/add_contact_widget.ui:268
+msgid "Send your friend a short message"
+msgstr ""
+
+#: src/ui/add_contact_widget.ui:298
+msgid "Send"
+msgstr "Enviar"
+
+#: src/ui/app_menu.ui:7
+#, fuzzy
+msgid "_Preferences"
+msgstr "Abrir preferencias"
+
+#: src/ui/app_menu.ui:13
+msgid "About"
+msgstr "Acerca de"
+
+#: src/ui/app_menu.ui:17
+msgid "_Quit"
+msgstr "_Dejar"
+
+#: src/ui/create_groupchat_widget.ui:112 src/ui/conference_info_widget.ui:39
+msgid "Conference"
+msgstr ""
+
+#: src/ui/conference_info_widget.ui:105
+msgid "Title:"
+msgstr "Título:"
+
+#: src/ui/conference_info_widget.ui:243 src/ui/user_info_widget.ui:449
+#: src/ui/friend_info_widget.ui:666
+msgid "Apply"
+msgstr "Aplicar"
+
+#: src/ui/conference_info_widget.ui:261
+msgid "Peers"
+msgstr "Pares"
+
+#: src/ui/conference_window.ui:209 src/ui/conversation_window.ui:268
+#: src/ui/user_info_widget.ui:177 src/ui/user_info_widget.ui:178
+#, fuzzy
+msgid "Insert Emoji"
+msgstr "Insertar Smiley"
+
+#: src/ui/contact_list_widget.ui:216
+msgid "Filter contacts by status"
+msgstr "Filtrar contactos por estado"
+
+#: src/ui/contact_list_widget.ui:222
msgid "All"
msgstr "Todo"
-#: ui/ContactListWindow.vala:1060 ui/ContactListWindow.vala:1082
-#, c-format
-msgid "Are you sure you want to delete '%s' from your contact list?"
-msgstr "¿Está seguro de querer eliminar '%s' de su lista de contactos?"
+#: src/ui/contact_list_widget.ui:329
+msgid "Add a contact"
+msgstr ""
-#: core/ToxSession.vala:33
-msgid "Away"
-msgstr "Ausente"
+#: src/ui/contact_list_widget.ui:371
+msgid "View file transfers"
+msgstr ""
-#: core/ToxSession.vala:717
-#, c-format
-msgid "Background thread started.\n"
-msgstr "Hilo de ejecución en segundo plano iniciado.\n"
+#: src/ui/contact_list_widget.ui:392
+msgid "Open preferences"
+msgstr "Abrir preferencias"
-#: core/ToxSession.vala:756
-#, c-format
-msgid "Background thread stopped.\n"
-msgstr "Hilo de ejecución en segundo plano detenido.\n"
+#: src/ui/conversation_window.ui:109
+msgid "Start a call"
+msgstr "Comience una llamada"
-#: core/Tools.vala:142
-msgid "Bad checksum"
-msgstr "Checksum erroneo"
+#: src/ui/conversation_window.ui:290
+msgid "Insert attachment"
+msgstr ""
-#: core/ToxSession.vala:35
-msgid "Busy"
-msgstr "Ocupado"
-
-#: ui/conversation_window.ui:156
-msgid "Call contact"
-msgstr "Llamar contacto"
-
-#: ui/conversation_window.ui:174
-msgid "Call contact with video"
-msgstr "Iniciar videollamada con contacto"
-
-#: core/Tools.vala:158 core/Tools.vala:171
-#, c-format
-msgid "Can't create action regex: %s.\n"
-msgstr "No se puede crear expresión regular de acción: %s.\n"
-
-#: core/SqliteTools.vala:75
-#, c-format
-msgid "Can't open database: %d: %s\n"
-msgstr "No se puede abrir la base de datos: %d: %s\n"
-
-#: core/Tools.vala:136
-msgid "Can't send to own key"
-msgstr "No se puede enviar a la clave propia"
-
-#: ui/FileTransferChatEntry.vala:119
-msgid "Canceled"
-msgstr "Cancelado"
-
-#: ui/contact_list.ui:72
-msgid "Change _Status"
-msgstr "Cambiar _Estado"
-
-#: ui/ContactListWindow.vala:670
-msgid "Connected to the network"
-msgstr "Conectado a la red"
-
-#: core/ToxSession.vala:720
-#, c-format
-msgid "Connecting to DHT Nodes:\n"
-msgstr "Conectando a los nodos DHT:\n"
-
-#: ui/ContactListWindow.vala:668
-#, c-format
-msgid "Connection to DHT %s.\n"
-msgstr "Conexión al DHT %s.\n"
-
-#: ui/ContactListWindow.vala:907
-#, c-format
-msgid "Contact accepted file sending request\n"
-msgstr "Contacto aceptó la solicitud de envío de archivo\n"
-
-#: ui/ContactListWindow.vala:508
-#, c-format
-msgid "Copied Tox ID to clipboard\n"
-msgstr "Tox ID copiado al portapapeles\n"
-
-#: ui/ContactListWindow.vala:1135
-#, c-format
-msgid "Could not add friend: %s.\n"
-msgstr "No se pudo añadir contacto: %s.\n"
-
-#: ui/ContactListWindow.vala:1123
-msgid "Could not add friend: Invalid ID\n"
-msgstr "No se pudo añadir contacto: ID Invalida\n"
-
-#: core/SqliteTools.vala:40
-#, c-format
-msgid "Could not bind int to %s."
-msgstr "No se pudo enlazar int a %s."
-
-#: core/SqliteTools.vala:50
-#, c-format
-msgid "Could not bind int64 to %s."
-msgstr "No se pudo enlazar int64 a %s."
-
-#: core/SqliteTools.vala:60
-#, c-format
-msgid "Could not bind text to %s"
-msgstr "No se pudo enlazar texto a %s."
-
-#: ui/ContactListWindow.vala:447
-#, c-format
-msgid "Could not change user name!\n"
-msgstr "No se pudo cambiar el nombre!\n"
-
-#: ui/ContactListWindow.vala:455
-#, c-format
-msgid "Could not change user statusmessage!\n"
-msgstr "No se pudo cambiar el estado!\n"
-
-#: ui/ContactListWindow.vala:1189
-#, c-format
-msgid "Could not create a new groupchat.\n"
-msgstr "No se pudo crear un nuevo chat grupal.\n"
-
-#: ui/ContactListWindow.vala:725
-#, c-format
-msgid "Could not join groupchat.\n"
-msgstr "No se pudo unir al chat grupal.\n"
-
-#: ui/ContactListWindow.vala:146
-#, c-format
-msgid "Could not load session data (%s), creating new one.\n"
-msgstr "No se pudo cargar data de sesión (%s), creando una nueva.\n"
-
-#: ui/ContactListWindow.vala:130
-#, c-format
-msgid "Could not read theme from \"%s\""
-msgstr "No se pudo leer tema de \"%s\""
-
-#: ui/ContactListWindow.vala:1090
-#, c-format
-msgid "Could not remove %s.\n"
-msgstr "No se pudo eliminar %s.\n"
-
-#: ui/ContactListWindow.vala:1068
-#, c-format
-msgid "Could not remove contact %i.\n"
-msgstr "No se pudo eliminar contacto %i.\n"
-
-#: core/ToxSession.vala:352
-#, c-format
-msgid "Could not remove peer [%i] from groupchat #%i (no such peer)\n"
-msgstr ""
-"No se pudo remover al peer [%i] del chat grupal #%i (peer no encontrado)\n"
-
-#: ui/ContactListWindow.vala:1112
-msgid "Could not resolve ID from DNS record\n"
-msgstr "No se pudo resolver el Tox ID del record de DNS\n"
-
-#: ui/contact_list.ui:416
-msgid "Create groupchat"
-msgstr "Crear un chat grupal"
-
-#: ui/settings_window.ui:301
-msgid "Default Tox DNS ID suffix:"
-msgstr "Sufijo de fault de ID DNS de Tox:"
-
-#: ui/FileTransferChatEntry.vala:125 ui/FileTransferChatEntry.vala:129
-msgid "Disconnected"
-msgstr "Desconectado"
-
-#: ui/ContactListWindow.vala:673
-msgid "Disconnected from the network"
-msgstr "Desconectado de la red"
-
-#: ui/UserInfoWindow.vala:86
-msgid "Edit user information"
-msgstr "Editar información de usuario"
-
-#: ui/ContactListWindow.vala:899
-#, c-format
-msgid "Ended file transfer for %s to %s\n"
-msgstr "Finalizó transferencia de archivo para %s de %s\n"
-
-#: ui/ContactListWindow.vala:102
-#, c-format
-msgid "Ending session...\n"
-msgstr "Finalizando sesión...\n"
-
-#: ui/add_contact_dialog.ui:40
-msgid "Enter a Tox ID here or a Tox URI"
-msgstr "Inserte un Tox ID o un Tox URI aquí"
-
-#: core/ContactStorage.vala:108
-#, c-format
-msgid "Error creating contacts insert statement: %d: %s\n"
-msgstr "Error al crear statement de inserción de contactos: %d: %s\n"
-
-#: core/ContactStorage.vala:113
-#, c-format
-msgid "Error creating contacts select statement: %d: %s\n"
-msgstr "Error al crear statement de selección de contactos: %d: %s\n"
-
-#: core/ContactStorage.vala:103
-#, c-format
-msgid "Error creating contacts table: %s\n"
-msgstr "Error al crear tabla de contactos: %s\n"
-
-#: core/DhtNodeStorage.vala:177
-#, c-format
-msgid "Error creating dht nodes insert statement: %d: %s\n"
-msgstr "Error al crear statement de inserción de nodos DHT: %d: %s\n"
-
-#: core/DhtNodeStorage.vala:182
-#, c-format
-msgid "Error creating dht nodes select statement: %d: %s\n"
-msgstr "Error al crear statement de selección de nodos DHT: %d: %s\n"
-
-#: core/DhtNodeStorage.vala:172
-#, c-format
-msgid "Error creating dht nodes table: %s\n"
-msgstr "Error al crear tabla de nodos DHT: %s\n"
-
-#: core/ToxDns.vala:36
-#, c-format
-msgid "Error creating tox dns regex: %s\n"
-msgstr "Error al crear expresión regular de dns de Tox: %s\n"
-
-#: core/ToxDns.vala:51
-#, c-format
-msgid "Error creating tox uri regex: %s\n"
-msgstr "Error al crear expresión regular de uri de Tox: %s\n"
-
-#: ui/ConversationTextView.vala:184
-#, c-format
-msgid "Error matching uri regex: %s\n"
-msgstr "Error al igualar expresión regular de uri: %s\n"
-
-#: ui/ConversationWidget.vala:308
-#, c-format
-msgid "Error occured while getting file size: %s"
-msgstr "Error al intentar obtener tamaño de archivo: %s"
-
-#: core/ToxSession.vala:111
-#, c-format
-msgid "Error opening database: %s\n"
-msgstr "Error al abrir base de datos: %s\n"
-
-#: core/Settings.vala:112
-#, c-format
-msgid "Error reading configs:%s\n"
-msgstr "Error al leer configuraciones: %s\n"
-
-#: core/ToxDns.vala:81
-#, c-format
-msgid "Error resolving name: %s\n"
-msgstr "Error al resolver nombre: %s\n"
-
-#: core/MessageLog.vala:135
-#, c-format
-msgid "Error retrieving logs from sqlite database: %s\n"
-msgstr "Error al recuperar logs de la base de datos sqlite: %s\n"
-
-#: core/Settings.vala:99
-#, c-format
-msgid "Error saving configs:%s\n"
-msgstr "Error al guardar configuraciones: %s\n"
-
-#: core/Tools.vala:123
-#, c-format
-msgid "Error when doing uri markup: %s"
-msgstr "Error al hacer marcado de uri: %s"
-
-#: ui/ConversationTextView.vala:245
-#, c-format
-msgid "Error when showing uri: %s\n"
-msgstr "Error al mostrar uri: %s\n"
-
-#: ui/ContactListWindow.vala:168
-#, c-format
-msgid "Error while loading icon: %s\n"
-msgstr "Error en la carga del ícono: %s\n"
-
-#: core/ResourceFactory.vala:126
-#, c-format
-msgid "Error while loading image from \"%s\":%s\n"
-msgstr "Error en la carga de la imagen de \"%s\":%s\n"
-
-#: core/ToxSession.vala:801
-msgid "Error while loading messenger data."
-msgstr "Error en la carga de información de mensajería."
-
-#: core/ToxSession.vala:795
-msgid "Error while reading from stream."
-msgstr "Error en la lectura del stream."
-
-#: ui/FileTransferChatEntry.vala:171
-#, c-format
-msgid "Error while trying to create file: %s\n"
-msgstr "Error al intentar crear archivo: %s\n"
-
-#: ui/ContactListWindow.vala:961
-#, c-format
-msgid "Error while trying to write data to file\n"
-msgstr "Error al intentar escribir a archivo\n"
-
-#: core/ToxSession.vala:828
-msgid "Error while writing to stream."
-msgstr "Error en la escritura al stream."
-
-#: core/ContactStorage.vala:88
-#, c-format
-msgid "Error writing contact to sqlite database: %s\n"
-msgstr "Error al escribir contacto en la base de datos sqlite: %s\n"
-
-#: core/MessageLog.vala:118
-#, c-format
-msgid "Error writing message to sqlite database: %s\n"
-msgstr "Error al escribir mensaje en la base de datos sqlite: %s\n"
-
-#: core/MessageLog.vala:186 core/MessageLog.vala:193
-#, c-format
-msgid "Error: %d: %s\n"
-msgstr "Error: %d: %s\n"
-
-#: core/MessageLog.vala:169 core/MessageLog.vala:179
-#: ui/ConversationView.vala:78
-#, c-format
-msgid "Error: %s\n"
-msgstr "Error: %s\n"
-
-#: core/ToxSession.vala:788
-#, c-format
-msgid "File \"%d\" does not exist."
-msgstr "Archivo \"%d\" no existe."
-
-#: ui/ContactListWindow.vala:929
-#, c-format
-msgid "File transfer finished for file number %u"
-msgstr "Transferencia de archivo finalizada para número de archivo %u"
-
-#: ui/ContactListWindow.vala:925
-#, c-format
-msgid "File transfer was rejected for file number %u"
-msgstr "Transferencia de archivo rechazada para número de archivo %u"
-
-#: ui/FileTransferChatEntry.vala:94
-msgid "File was rejected"
-msgstr "El archivo fue rechazado."
-
-#: ui/settings_window.ui:236
-msgid "Flash window when a new message arrives"
-msgstr "Parpadear ventana cuando llega un nuevo mensaje"
-
-#: ui/ContactListWindow.vala:614
-#, c-format
-msgid "Friend could not be added.\n"
-msgstr "El contacto no pudo ser añadido.\n"
-
-#: core/Tools.vala:138
-msgid "Friend request already sent"
-msgstr "Petición de amistad ya enviada"
-
-#: core/Tools.vala:148
-msgid "Friend request successfully sent"
-msgstr "Petición de amistad enviada con éxito"
-
-#: ui/ContactListWindow.vala:1142
-#, c-format
-msgid "Friend request successfully sent. Friend added as %i.\n"
-msgstr "Petición de amistad enviada con éxito. Contacto añadido como %i.\n"
-
-#: ui/ContactListWindow.vala:771
-#, c-format
-msgid "Group action from unknown contact #%i [%i]\n"
-msgstr "Acción grupal de contacto desconocido #%i [%i]\n"
-
-#: ui/ContactListWindow.vala:708
-#, c-format
-msgid "Group invite from %s with public key %s\n"
-msgstr "Invitación grupal de %s con clave pública %s\n"
-
-#: ui/ContactListWindow.vala:742
-#, c-format
-msgid "Group message from unknown contact #%i [%i]\n"
-msgstr "Mensaje grupal de contacto desconocido #%i [%i]\n"
-
-#: core/GroupChat.vala:45
-#, c-format
-msgid "Groupchat #%i"
-msgstr "Chat grupal #%i"
-
-#: ui/ContactListWindow.vala:896
-#, c-format
-msgid "I/O error while trying to close file stream: %s\n"
-msgstr "Error de I/O al intentar cerrar stream de archivo: %s\n"
-
-#: ui/ContactListWindow.vala:888
-#, c-format
-msgid "I/O error while trying to read file: %s\n"
-msgstr "Error de I/O al intentar leer archivo: %s\n"
-
-#: ui/AddContactDialog.vala:96
-msgid "ID contains invalid characters"
-msgstr "El Tox ID contiene caracteres invalidos"
-
-#: ui/user_info_window.ui:40
-msgid "ID:"
-msgstr "ID:"
+#: src/ui/create_groupchat_widget.ui:93
+msgid "_Title:"
+msgstr "_Título:"
-#: ui/ContactListWindow.vala:86
-#, c-format
-msgid "ID: %s\n"
-msgstr "Tox ID: %s\n"
+#: src/ui/create_groupchat_widget.ui:179
+msgid "T_ype:"
+msgstr "Tipo:"
-#: ui/user_info_window.ui:222
-msgid "Icon:"
-msgstr "Ícono:"
+#: src/ui/create_groupchat_widget.ui:271
+msgid "Create"
+msgstr "Crear"
-#: core/SqliteTools.vala:37 core/SqliteTools.vala:47 core/SqliteTools.vala:57
-#, c-format
-msgid "Index for %s not found."
-msgstr "Índice para %s no encontrado."
+#: src/ui/file_transfer_widget.ui:35
+msgid "File transfers"
+msgstr ""
-#: ui/conversation_window.ui:290
-msgid "Insert Smiley"
-msgstr "Insertar Smiley"
+#: src/ui/friend_info_widget.ui:45
+msgid "Friend profile"
+msgstr ""
-#: core/ToxDns.vala:113
-#, c-format
-msgid "Invalid record\n"
-msgstr "Record invalido\n"
+#: src/ui/friend_info_widget.ui:62
+msgid "Remove from your friends list"
+msgstr "Eliminar de tu lista de amigos"
-#: core/ToxDns.vala:64
-#, c-format
-msgid "Invalid tox uri\n"
-msgstr "URI de Tox invalido\n"
+#: src/ui/user_info_widget.ui:113 src/ui/friend_info_widget.ui:111
+msgid "Username:"
+msgstr "Nombre de usuario:"
-#: ui/ContactListWindow.vala:728
-#, c-format
-msgid "Joined Groupchat #%i\n"
-msgstr "Unido al chat grupal #%i\n"
+#: src/ui/user_info_widget.ui:206 src/ui/friend_info_widget.ui:200
+msgid "Image:"
+msgstr "Imagen:"
-#: ui/settings_window.ui:18
-msgid "KB/MB"
-msgstr "KB/MB"
+#: src/ui/friend_info_widget.ui:245
+msgid "Last seen:"
+msgstr ""
+
+#: src/ui/friend_info_widget.ui:290
+msgid "Alias:"
+msgstr "Alias:"
-#: ui/settings_window.ui:78
-msgid "Keep history"
-msgstr "Mantener historial"
+#: src/ui/friend_info_widget.ui:321
+msgid "Set a custom alias to quickly find your friends"
+msgstr "Establece un alias personalizado para encontrar rápidamente a tus amigos"
+
+#: src/ui/user_info_widget.ui:291 src/ui/friend_info_widget.ui:579
+msgid "Tox"
+msgstr "Tox"
+
+#: src/ui/user_info_widget.ui:330 src/ui/friend_info_widget.ui:612
+msgid "ID:"
+msgstr "ID:"
-#: ui/settings_window.ui:14
+#: src/ui/message_widget.ui:91
+msgid "Message sent ✓"
+msgstr ""
+
+#: src/ui/message_widget.ui:107
+msgid "Message received ✓"
+msgstr ""
+
+#: src/ui/peer_entry.ui:55
+msgid "This peer is also in your friends list"
+msgstr "Este par también está en tu lista de amigos"
+
+#: src/ui/settings_widget.ui:38
msgid "KiB/MiB"
msgstr "KiB/MiB"
-#: core/Contact.vala:117
-#, c-format
-msgid "Last seen: %s"
-msgstr "Visto por última vez: %s"
+#: src/ui/settings_widget.ui:42
+msgid "KB/MB"
+msgstr "KB/MB"
-#: ui/AddContactDialog.vala:53
-#, c-format
-msgid "Loading add contact window failed!\n"
-msgstr "Carga de la ventana de añadir contactos fallida!\n"
+#: src/ui/settings_widget.ui:98
+msgid "General"
+msgstr "General"
-#: ui/ConversationWidget.vala:71 ui/SettingsWindow.vala:32
-#, c-format
-msgid "Loading conversation window failed!\n"
-msgstr "Carga de la ventana de conversación fallida!\n"
+#: src/ui/settings_widget.ui:268
+msgid "Appearance"
+msgstr "Apariencia"
-#: ui/FileTransferChatEntry.vala:40
-#, c-format
-msgid "Loading message widget failed!\n"
-msgstr "Carga del widget de mensaje fallida!\n"
+#: src/ui/settings_widget.ui:313
+msgid "Dark Theme"
+msgstr "Tema oscuro"
-#: core/Tools.vala:132
-msgid "Message too long"
-msgstr "Mensaje demasiado largo"
+#: src/ui/settings_widget.ui:523
+msgid "Minimize to tray"
+msgstr "Minimizar a la bandeja"
-#: ui/settings_window.ui:337
-msgid "Miscellaneous"
-msgstr "Misceláneo"
+#: src/ui/settings_widget.ui:619
+msgid "Privacy"
+msgstr "Privacidad"
-#: ui/user_info_window.ui:192
-msgid "Name:"
-msgstr "Nombre:"
+#: src/ui/settings_widget.ui:663
+msgid "Send typing notifications"
+msgstr ""
-#: ui/ContactListWindow.vala:604
-#, c-format
-msgid ""
-"New friend request from '%s'.\n"
-"Do you want to accept?"
+#: src/ui/settings_widget.ui:676
+msgid "Show others when I am typing"
msgstr ""
-"Nueva petición de amistad de '%s'.\n"
-"¿Quiere aceptar?"
-#: ui/AddContactDialog.vala:90
-msgid "No ID given"
-msgstr "Ningún ID insertado"
+#: src/ui/settings_widget.ui:759
+msgid "History"
+msgstr ""
+
+#: src/ui/settings_widget.ui:893
+msgid "days"
+msgstr "días"
+
+#: src/ui/settings_widget.ui:923
+msgid "Delete all previous conversations"
+msgstr "Eliminar todas las conversaciones anteriores"
+
+#: src/ui/settings_widget.ui:1340
+msgid "Update bootstrap nodes"
+msgstr "Actualizar los nodos de arranque"
+
+#: src/ui/user_info_widget.ui:79
+msgid "User profile"
+msgstr "Perfil del usuario"
+
+#: src/ui/user_info_widget.ui:372
+#, fuzzy
+msgid "Copy to clipboard"
+msgstr "_Copiar ID al portapapeles"
+
+#: src/ui/welcome_widget.ui:40
+msgid "A new kind of instant messaging"
+msgstr "Un nuevo tipo de mensajería instantánea"
-#: core/Tools.vala:134
-msgid "No message included"
-msgstr "Ningún mensaje incluido"
+#: src/ui/welcome_widget.ui:56
+msgid "Chat with your friends and family without anyone else listening in."
+msgstr "Chatea con tus amigos y familiares sin que nadie más te escuche."
-#: core/ToxDns.vala:103
-#, c-format
-msgid "No pin privided, aborting...\n"
-msgstr "No hay PIN provisto, abortando...\n"
+#: src/ui/welcome_widget.ui:109
+msgid "Learn more"
+msgstr "Aprende más"
-#: ui/contact_list.ui:118
-msgid "O_ffline"
-msgstr "F_uera de línea"
+#: src/core/Message.vala:76 src/viewmodel/MessageViewModel.vala:87
+#: src/tox/ConferenceMessage.vala:56
+msgid "me"
+msgstr "yo"
-#: core/Contact.vala:98 core/Contact.vala:108 core/ToxSession.vala:37
+#: src/ui/user_info_widget.ui:244
+msgid "Choose an avatar"
+msgstr "Elige un avatar"
+
+#: src/ui/friend_request_widget.ui:146
+msgid "Reject request"
+msgstr "Rechazar solicitud"
+
+#: src/ui/friend_request_widget.ui:170
+msgid "Accept request"
+msgstr "Aceptar petición"
+
+#: src/ui/application_window.ui:55
+msgid "venom"
+msgstr ""
+
+#: src/core/NotificationListener.vala:76
+msgid "New file from %s"
+msgstr ""
+
+#: src/viewmodel/ContactListEntryViewModel.vala:58
+msgid "New Message!"
+msgstr ""
+
+#: src/viewmodel/ContactListEntryViewModel.vala:64
msgid "Offline"
-msgstr "Fuera de línea"
+msgstr ""
-#: core/GroupChatContact.vala:32 core/ToxSession.vala:31
-#: ui/ContactListWindow.vala:208
+#: src/viewmodel/ContactListEntryViewModel.vala:72
+#: src/ui/user_status_menu.ui:11
+msgid "Away"
+msgstr ""
+
+#: src/viewmodel/ContactListEntryViewModel.vala:74
+#: src/ui/user_status_menu.ui:17
+msgid "Busy"
+msgstr ""
+
+#: src/viewmodel/ContactListEntryViewModel.vala:76 src/ui/user_status_menu.ui:5
msgid "Online"
-msgstr "En línea"
+msgstr ""
-#: ui/contact_list.ui:449
-msgid "Open preferences"
-msgstr "Abrir preferencias"
+#: src/viewmodel/MessageViewModel.vala:65
+msgid "Today at %s"
+msgstr ""
-#: core/Tools.vala:146
-msgid "Out of memory"
-msgstr "Sin memoria"
+#: src/viewmodel/MessageViewModel.vala:69
+msgid "Yesterday at %s"
+msgstr ""
-#: ui/FileTransferChatEntry.vala:104
-msgid "Paused"
-msgstr "Pausado"
+#: src/tox/Conference.vala:43
+msgid "Unnamed conference %u"
+msgstr ""
-#: ui/PinDialog.vala:37
-#, c-format
-msgid ""
-"Please insert PIN for \n"
-"%s"
+#: src/tox/ToxSession.vala:645
+msgid "Address must consist of 76 hexadecimal characters"
msgstr ""
-"Por favor insertar PIN para \n"
-"%s"
-#: ui/PinDialog.vala:49
-msgid "Please insert PIN..."
-msgstr "Por favor insertar PIN..."
+#: src/view/ConversationWindow.vala:102
+msgid "%s is typing..."
+msgstr ""
-#: ui/add_contact_dialog.ui:6
-msgid "Please let me add you to my contact list."
-msgstr "Por favor dejame agregarte a mi lista de contactos."
+#: src/view/ConversationWindow.vala:168 src/view/FileTransferEntry.vala:76
+msgid "_Cancel"
+msgstr ""
-#: ui/settings_window.ui:221
-msgid "Privacy"
-msgstr "Privacidad"
+#: src/view/ConversationWindow.vala:169
+msgid "_Open"
+msgstr ""
-#: ui/ContactListWindow.vala:869
-#, c-format
-msgid "Read incorrect number of bytes from file\n"
-msgstr "Se leyó un número incorrecto de bytes del archivo\n"
-
-#: ui/FileTransferChatEntry.vala:113
-msgid "Receiving failed"
-msgstr "Recibimiento fallido"
-
-#: ui/ContactListWindow.vala:1114
-msgid "Resolving ID failed"
-msgstr "Resolvimiento de ID fallido"
-
-#: ui/ContactListWindow.vala:427
-#, c-format
-msgid "Retrieved contact %s from savefile.\n"
-msgstr "Contacto %s recuperado de archivo de guardado.\n"
-
-#: Main.vala:50
-#, c-format
-msgid "Run '%s --help' to see a full list of available command line options.\n"
-msgstr ""
-"Ejecute '%s --help' para ver una lista entera de las opciones de línea de "
-"comando disponibles.\n"
-
-#: core/MessageLog.vala:86
-#, c-format
-msgid "SQLite database closed.\n"
-msgstr "Base de datos SQLite cerrada.\n"
-
-#: core/MessageLog.vala:82
-#, c-format
-msgid "SQLite database created.\n"
-msgstr "Base de datos SQLite creada.\n"
-
-#: ui/FileTransferChatEntry.vala:158
-msgid "Save"
-msgstr "Guardar"
-
-#: ui/FileTransferChatEntry.vala:155
-msgid "Save file"
-msgstr "Guardar archivo"
-
-#: ui/ContactListWindow.vala:120
-#, c-format
-msgid "Saving session file failed: %s\n"
-msgstr "Guardado de archivo de sesión fallido: %s\n"
-
-#: ui/FileTransferChatEntry.vala:165
-#, c-format
-msgid "Saving to: %s\n"
-msgstr "Guardando a: %s\n"
-
-#: ui/ContactListWindow.vala:116
-#, c-format
-msgid "Saving tox session data\n"
-msgstr "Guardando información de sesión de Tox\n"
-
-#: ui/ConversationWidget.vala:282
-msgid "Select"
-msgstr "Seleccionar"
-
-#: ui/ConversationWidget.vala:279
-msgid "Select a file to send"
-msgstr "Seleccionar un archivo a enviar"
-
-#: ui/add_contact_dialog.ui:113
-msgid "Send a custom message to be displayed to the friend you are adding"
-msgstr "Envíe un mensaje personalizado para el contacto que está agregando"
+#: src/view/FileTransferEntry.vala:77
+msgid "_Save"
+msgstr ""
-#: ui/conversation_window.ui:308
-msgid "Send file"
-msgstr "Enviar archivo"
+#: src/ui/file_transfer_widget.ui:117
+msgid "No file transfers yet …"
+msgstr ""
-#: ui/conversation_window.ui:341
-msgid "Send message"
-msgstr "Enviar mensaje"
+#: src/ui/file_transfer_entry.ui:34
+msgid "Remove transfer"
+msgstr ""
-#: ui/FileTransferChatEntry.vala:107
-msgid "Sending failed"
-msgstr "Envio fallido"
+#: src/ui/file_transfer_entry.ui:102
+msgid "Open file"
+msgstr ""
-#: ui/ContactListWindow.vala:111
-#, c-format
-msgid "Session ended gracefully.\n"
-msgstr "Sesión terminada con éxito.\n"
+#: src/ui/file_transfer_entry.ui:126
+msgid "Start transfer"
+msgstr ""
-#: ui/add_contact_dialog.ui:67
-msgid "Set a custom nickname for the friend you are about to add"
+#: src/ui/file_transfer_entry.ui:147
+msgid "Pause transfer"
msgstr ""
-"Establezca un nombre personalizado para el contacto que está por agregar"
-#: core/Tools.vala:144
-msgid "Set new nospam"
-msgstr "Establecer nuevo valor nospam"
+#: src/ui/file_transfer_entry.ui:168
+msgid "Stop transfer"
+msgstr ""
-#: ui/settings_window.ui:30
-msgid "Settings"
-msgstr "Opciones"
+#: src/ui/create_groupchat_widget.ui:199
+msgid "Text"
+msgstr ""
-#: core/Settings.vala:102
-#, c-format
-msgid "Settings saved.\n"
-msgstr "Opciones guardadas.\n"
+#: src/ui/create_groupchat_widget.ui:214
+msgid "Speech"
+msgstr ""
-#: ui/settings_window.ui:186
-msgid "Show _others when I am typing"
-msgstr "Mostrar a _otros cuando estoy escribiendo"
+#: src/ui/peer_entry.ui:68
+msgid "That's you"
+msgstr ""
-#: ui/settings_window.ui:258
-msgid "Show filesize in"
-msgstr "Mostrar tamaño de archivo en"
+#: src/ui/welcome_widget.ui:156
+msgid "Get involved"
+msgstr ""
-#: ui/settings_window.ui:202
-msgid "Show me when others are typing"
-msgstr "Mostrarme cuando otros escriben"
+#: src/ui/settings_widget.ui:181
+msgid "Proxy"
+msgstr ""
-#: Main.vala:70
-#, c-format
-msgid "Starting in offline mode\n"
-msgstr "Starting in offline mode\n"
+#: src/ui/settings_widget.ui:326
+msgid "Use a dark variant of the theme"
+msgstr ""
-#: ui/user_info_window.ui:178
-msgid "Status message:"
-msgstr "Estado:"
+#: src/ui/settings_widget.ui:383
+msgid "Animations"
+msgstr ""
-#: ui/ContactListWindow.vala:408
-#, c-format
-msgid "Theme refreshed\n"
-msgstr "Tema actualizado\n"
+#: src/ui/settings_widget.ui:396
+msgid "Enable animated transitions"
+msgstr ""
-#: ui/Client.vala:116
-msgid "There is currently no help available"
-msgstr "Actualmente no hay ayuda disponible"
+#: src/ui/settings_widget.ui:453
+msgid "Notifications"
+msgstr ""
-#: core/ResourceFactory.vala:77
-msgid "Tox User"
-msgstr "Usuario de Tox"
+#: src/ui/settings_widget.ui:466
+msgid "Show notifications for unread messages"
+msgstr ""
-#: core/ResourceFactory.vala:78
-#, c-format
-msgid "Toxing on Venom v.%s"
-msgstr "Toxeando desde Venom v.%s"
-
-#: ui/ContactListWindow.vala:826
-#, c-format
-msgid "Trying to send unknown file"
-msgstr "Tratando de enviar archivo desconocido"
-
-#: ui/MessageTextView.vala:27
-msgid "Type your message here..."
-msgstr "Escriba su mensaje aquí..."
-
-#: core/Tools.vala:140
-msgid "Unknown error"
-msgstr "Error desconocido"
-
-#: ui/ContactListWindow.vala:890
-#, c-format
-msgid "Unknown error while trying to read file: %s\n"
-msgstr "Error desconocido al intentar leer archivo: %s\n"
-
-#: Main.vala:65
-#, c-format
-msgid "Using Gtk.TextView to display messages\n"
-msgstr "Usando Gtk.TextView para mostrar mensajes\n"
-
-#: Main.vala:60
-#, c-format
-msgid "Using data file \"%s\"\n"
-msgstr "Usando archivo de data \"%s\"\n"
-
-#: ui/AddContactDialog.vala:100
-msgid "Valid ID size"
-msgstr "Tamaño de ID valido"
-
-#: ui/ContactListWindow.vala:461
-#, c-format
-msgid "Venom (%s)"
-msgstr "Venom (%s)"
-
-#: ui/ConversationTextView.vala:139
-#, c-format
-msgid "[%s] "
-msgstr "[%s] "
-
-#: ui/ContactListWindow.vala:638
-#, c-format
-msgid "[ac] %i:%s\n"
-msgstr "[ac] %i:%s\n"
-
-#: ui/ContactListWindow.vala:598
-#, c-format
-msgid "[fr] %s:%s\n"
-msgstr "[fr] %s:%s\n"
-
-#: ui/ContactListWindow.vala:763
-#, c-format
-msgid "[ga] %s [%i]@%i: %s\n"
-msgstr "[ga] %s [%i]@%i: %s\n"
-
-#: ui/ContactListWindow.vala:734
-#, c-format
-msgid "[gm] %s [%i]@%i: %s\n"
-msgstr "[gm] %s [%i]@%i: %s\n"
-
-#: ui/ContactListWindow.vala:660
-#, c-format
-msgid "[rr] %s:%u\n"
-msgstr "[rr] %s:%u\n"
-
-#: ui/ContactListWindow.vala:656
-#, c-format
-msgid "[us] %s:%i\n"
-msgstr "[us] %s:%i\n"
-
-#: ui/contact_list.ui:96
-msgid "_Away"
-msgstr "_Ausente"
-
-#: ui/user_info_window.ui:254
-msgid "_Browse..."
-msgstr "_Examinar..."
-
-#: ui/contact_list.ui:107
-msgid "_Busy"
-msgstr "_Ocupado"
-
-#: ui/contact_list.ui:61
-msgid "_Copy ID to clipboard"
-msgstr "_Copiar ID al portapapeles"
+#: src/ui/settings_widget.ui:536
+msgid "Minimize app to system tray on close"
+msgstr ""
-#: ui/contact_list.ui:50
-msgid "_Edit user"
-msgstr "_Editar usuario"
+#: src/ui/settings_widget.ui:823
+msgid "Keep forever"
+msgstr ""
-#: ui/add_contact_dialog.ui:94
-msgid "_Message (optional):"
-msgstr "_Mensaje (opcional):"
+#: src/ui/settings_widget.ui:860
+msgid "Remove older than"
+msgstr ""
+
+#: src/ui/settings_widget.ui:1017
+msgid "Connection"
+msgstr ""
+
+#: src/ui/settings_widget.ui:1060
+msgid "UDP"
+msgstr ""
-#: ui/add_contact_dialog.ui:54
-msgid "_Nickname (optional):"
-msgstr "_Sobrenombre (opcional):"
+#: src/ui/settings_widget.ui:1130
+msgid "IPv6"
+msgstr ""
-#: ui/contact_list.ui:85
-msgid "_Online"
-msgstr "_En Línea"
+#: src/ui/settings_widget.ui:1143
+msgid "Allow both IPv4 and IPv6 communication"
+msgstr ""
-#: ui/add_contact_dialog.ui:27
-msgid "_Tox ID:"
-msgstr "_Tox ID:"
+#: src/ui/settings_widget.ui:1200
+msgid "Local discovery"
+msgstr ""
-#: ui/contact_list.ui:278
-msgid "connecting..."
-msgstr "conectando..."
+#: src/ui/settings_widget.ui:1213
+msgid "Look for peers on the local network"
+msgstr ""
-#: ui/settings_window.ui:160
-msgid "days"
-msgstr "días"
+#: src/ui/settings_widget.ui:1270
+msgid "Hole punching"
+msgstr ""
+
+#: src/ui/settings_widget.ui:1283
+msgid "Enable UDP hole punching"
+msgstr ""
+
+#: src/ui/settings_widget.ui:1376
+msgid "Bootstrap nodes"
+msgstr ""
+
+#: src/ui/settings_widget.ui:1511
+msgid "Proxy"
+msgstr ""
+
+#: src/ui/settings_widget.ui:1578
+msgid "System settings"
+msgstr ""
+
+#: src/ui/settings_widget.ui:1591
+msgid "Use your systems proxy settings"
+msgstr ""
+
+#: src/ui/settings_widget.ui:1645
+msgid "Manual settings"
+msgstr ""
+
+#: src/ui/settings_widget.ui:1658
+msgid "Use custom proxy settings"
+msgstr ""
+
+#: src/ui/settings_widget.ui:1699
+msgid "Host"
+msgstr ""
+
+#: src/ui/settings_widget.ui:1739
+msgid "Set a SOCKS5 proxy to connect to"
+msgstr ""
+
+#: src/ui/friend_info_widget.ui:309
+msgid "Reset alias"
+msgstr ""
+
+#: src/ui/friend_info_widget.ui:428
+msgid "Auto accept conference invites"
+msgstr ""
+
+#: src/ui/friend_info_widget.ui:474
+msgid "Auto accept file transfers"
+msgstr ""
+
+#: src/ui/friend_info_widget.ui:517
+msgid "Save files to"
+msgstr ""
+
+#: src/viewmodel/ContactListViewModel.vala:102
+msgid "New conference…"
+msgstr ""
+
+#: src/viewmodel/ContactListViewModel.vala:115
+msgid "Invite to conference"
+msgstr ""
+
+#: src/viewmodel/ContactListViewModel.vala:118
+msgid "Show details"
+msgstr ""
+
+#: src/viewmodel/ContactListViewModel.vala:140
+msgid "%u new friend request"
+msgid_plural "%u new friend requests"
+msgstr[0] ""
+msgstr[1] ""
+
+#: src/viewmodel/ContactListViewModel.vala:148
+msgid "%u new conference invite"
+msgid_plural "%u new conference invites"
+msgstr[0] ""
+msgstr[1] ""
+
+#: src/viewmodel/MessageViewModel.vala:51
+msgid "Just now"
+msgstr ""
+
+#: src/viewmodel/MessageViewModel.vala:56
+msgid "%u minute ago"
+msgid_plural "%u minutes ago"
+msgstr[0] ""
+msgstr[1] ""
+
+#: src/viewmodel/MessageViewModel.vala:61
+msgid "%u hour ago"
+msgid_plural "%u hours ago"
+msgstr[0] ""
+msgstr[1] ""
+
+#: src/ui/create_groupchat_widget.ui:59 src/ui/contact_list_widget.ui:350
+msgid "Create a conference"
+msgstr ""
+
+#: src/ui/create_groupchat_widget.ui:147
+msgid "Name the conference (optional)"
+msgstr ""
+
+#: src/ui/create_groupchat_widget.ui:242
+msgid "Select a conference type"
+msgstr ""
+
+#: src/ui/create_groupchat_widget.ui:288
+msgid "New conference"
+msgstr ""
+
+#: src/ui/create_groupchat_widget.ui:301 src/ui/create_groupchat_widget.ui:334
+msgid "Conference invites"
+msgstr ""
+
+#: src/ui/create_groupchat_widget.ui:390
+msgid "No new conference invites"
+msgstr ""
+
+#: src/ui/conversation_window.ui:134
+msgid "Start a video call"
+msgstr ""
+
+#: src/ui/friend_request_widget.ui:44
+msgid "_Public key:"
+msgstr ""
+
+#: src/ui/conference_info_widget.ui:56
+msgid "Leave Conference"
+msgstr ""
+
+#: src/ui/conference_info_widget.ui:174 src/ui/friend_info_widget.ui:357
+msgid "Show notifications"
+msgstr ""
+
+#: src/ui/conference_info_widget.ui:212 src/ui/friend_info_widget.ui:395
+msgid "Notifications have been globally disabled"
+msgstr ""
+
+#: src/ui/conference_invite_entry.ui:43
+msgid "Invite from:"
+msgstr ""
+
+#: src/ui/conference_invite_entry.ui:87
+msgid "Accept invite"
+msgstr ""
+
+#: src/ui/conference_invite_entry.ui:111
+msgid "Reject invite"
+msgstr ""
+
+#: src/ui/add_contact_widget.ui:30
+msgid "No new friend requests"
+msgstr ""
+
+#: src/ui/add_contact_widget.ui:315
+msgid "Add a friend"
+msgstr ""
+
+#: src/ui/add_contact_widget.ui:328 src/ui/add_contact_widget.ui:361
+msgid "Friend requests"
+msgstr ""
+
+#: src/ui/user_info_widget.ui:158 src/ui/friend_info_widget.ui:155
+msgid "Status message:"
+msgstr ""
+
+#: src/ui/settings_widget.ui:1073
+msgid "Use UDP communication when available"
+msgstr ""
-#: ui/settings_window.ui:127
-msgid "delete after"
-msgstr "eliminar despues de"
-
-#: Main.vala:49
-#, c-format
-msgid "error: %s\n"
-msgstr "error: %s\n"
-
-#: ui/ContactListWindow.vala:668
-msgid "established"
-msgstr "establecido"
-
-#: ui/ContactListWindow.vala:569
-#, c-format
-msgid "failed to send file %s to %s"
-msgstr "falló el envio de archivo %s a %s"
-
-#: ui/ContactListWindow.vala:1077
-#, c-format
-msgid "groupchat #%i"
-msgstr "chat grupal #%i"
-
-#: ui/settings_window.ui:104
-msgid "indefinitely"
-msgstr "indefinidamente"
-
-#: ui/ContactListWindow.vala:668
-msgid "lost"
-msgstr "perdido"
-
-#: core/GroupChat.vala:56
-msgid "no one connected"
-msgstr "nadie conectado"
-
-#: ui/ContactListWindow.vala:663
-msgid "offline"
-msgstr "fuera de línea"
-
-#: ui/ContactListWindow.vala:663
-msgid "online"
-msgstr "en línea"
-
-#: ui/ContactListWindow.vala:798
-#, c-format
-msgid "received file send request friend: %i filenumber: %i filename: %s \n"
-msgstr "received file send request friend: %i filenumber: %i filename: %s \n"
-
-#: ui/ContactListWindow.vala:562
-#, c-format
-msgid "sending file %s to %s\n"
-msgstr "enviando archivo %s a %s\n"
-
-#: ui/ContactListWindow.vala:1129
-#, c-format
-msgid "setting alias: %s\n"
-msgstr "establecido nuevo alias: %s\n"
-
-#: core/ToxDns.vala:95
-#, c-format
-msgid "tox 1 ID found: %s\n"
-msgstr "ID de tox 1 encontrado: %s\n"
-
-#: core/ToxDns.vala:100
-#, c-format
-msgid "tox 2 ID found: %s %s\n"
-msgstr "ID de tox 2 encontrado: %s %s\n"
-
-#: ui/AboutDialog.vala:46
-msgid "translator-credits"
-msgstr "oxichem"
diff --git a/po/fr.po b/po/fr.po
new file mode 100644
index 0000000..4b2002d
--- /dev/null
+++ b/po/fr.po
@@ -0,0 +1,635 @@
+msgid ""
+msgstr ""
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"X-Generator: POEditor.com\n"
+"Project-Id-Version: Venom\n"
+"Language: fr\n"
+"Plural-Forms: nplurals=2; plural=(n > 1);\n"
+
+#: src/core/Application.vala:32
+msgid "Set level of messages to log"
+msgstr "Définir le niveau des messages à journaliser"
+
+#: src/core/Application.vala:32
+msgid ""
+msgstr ""
+
+#: src/core/Application.vala:33
+msgid "Display version number"
+msgstr "Afficher le numéro de version"
+
+#: src/core/NotificationListener.vala:55
+msgid "New message from %s"
+msgstr "Nouveau message de %s"
+
+#: src/core/R.vala:70
+msgid "Tox User"
+msgstr "Utilisateur de Tox"
+
+#: src/tox/Conference.vala:47
+msgid "%u Peers online"
+msgstr "%u pairs en ligne"
+
+#: src/view/AboutDialog.vala:53
+msgid "Packagers"
+msgstr "Emballeurs"
+
+#: src/view/AboutDialog.vala:58
+msgid "translator-credits"
+msgstr "Derheynn, Antoine Turmel, Raphaël GUIGNARD"
+
+#: src/view/AboutDialog.vala:61
+msgid "Visit us on Github"
+msgstr "Visitez-nous sur Github"
+
+#: src/ui/add_contact_widget.ui:43
+msgid "Please let me add you to my contact list. 😁"
+msgstr "S'il vous plaît laissez-moi vous ajouter à ma liste de contacts. 😁"
+
+#: src/ui/add_contact_widget.ui:99
+msgid "Send a friend request"
+msgstr "Envoyer une demande d'amitié"
+
+#: src/ui/add_contact_widget.ui:133
+msgid "_ID:"
+msgstr "_ID:"
+
+#: src/ui/add_contact_widget.ui:150
+msgid "Enter a Tox ID or URI here"
+msgstr "Entrez un ID de tox ou un URI ici"
+
+#: src/ui/create_groupchat_widget.ui:113 src/ui/add_contact_widget.ui:154
+msgid "paste from clipboard"
+msgstr "coller du presse-papiers"
+
+#: src/ui/add_contact_widget.ui:188
+msgid "Enter your friends Tox ID"
+msgstr "Entrez vos amis Tox ID"
+
+#: src/ui/friend_request_widget.ui:78 src/ui/add_contact_widget.ui:220
+msgid "_Message:"
+msgstr "_Message:"
+
+#: src/ui/add_contact_widget.ui:246
+msgid "Send a custom message to be displayed to the friend you are adding"
+msgstr "Envoyez un message personnalisé à l'ami que vous ajoutez"
+
+#: src/ui/add_contact_widget.ui:268
+msgid "Send your friend a short message"
+msgstr "Envoyer un petit message à votre ami"
+
+#: src/ui/add_contact_widget.ui:298
+msgid "Send"
+msgstr "Envoyer"
+
+#: src/ui/app_menu.ui:7
+msgid "_Preferences"
+msgstr "_Préférences"
+
+#: src/ui/app_menu.ui:13
+msgid "About"
+msgstr "Sur"
+
+#: src/ui/app_menu.ui:17
+msgid "_Quit"
+msgstr "_Quitter"
+
+#: src/ui/create_groupchat_widget.ui:112 src/ui/conference_info_widget.ui:39
+msgid "Conference"
+msgstr "Conférence"
+
+#: src/ui/conference_info_widget.ui:105
+msgid "Title:"
+msgstr "Titre:"
+
+#: src/ui/conference_info_widget.ui:243 src/ui/user_info_widget.ui:449
+#: src/ui/friend_info_widget.ui:666
+msgid "Apply"
+msgstr "Appliquer"
+
+#: src/ui/conference_info_widget.ui:261
+msgid "Peers"
+msgstr "Les pairs"
+
+#: src/ui/conference_window.ui:209 src/ui/conversation_window.ui:268
+#: src/ui/user_info_widget.ui:177 src/ui/user_info_widget.ui:178
+msgid "Insert Emoji"
+msgstr "Insérer des emoji"
+
+#: src/ui/contact_list_widget.ui:216
+msgid "Filter contacts by status"
+msgstr "Filtrer les contacts par statut"
+
+#: src/ui/contact_list_widget.ui:222
+msgid "All"
+msgstr "Tous"
+
+#: src/ui/contact_list_widget.ui:329
+msgid "Add a contact"
+msgstr "Ajouter un contact"
+
+#: src/ui/contact_list_widget.ui:371
+msgid "View file transfers"
+msgstr "Afficher les transferts de fichiers"
+
+#: src/ui/contact_list_widget.ui:392
+msgid "Open preferences"
+msgstr "Ouvrir les préférences"
+
+#: src/ui/conversation_window.ui:109
+msgid "Start a call"
+msgstr "Démarrer un appel"
+
+#: src/ui/conversation_window.ui:290
+msgid "Insert attachment"
+msgstr "Insérer pièce jointe"
+
+#: src/ui/create_groupchat_widget.ui:93
+msgid "_Title:"
+msgstr "_Titre:"
+
+#: src/ui/create_groupchat_widget.ui:179
+msgid "T_ype:"
+msgstr "Type:"
+
+#: src/ui/create_groupchat_widget.ui:271
+msgid "Create"
+msgstr "Créer"
+
+#: src/ui/file_transfer_widget.ui:35
+msgid "File transfers"
+msgstr "Transferts de fichiers"
+
+#: src/ui/friend_info_widget.ui:45
+msgid "Friend profile"
+msgstr "Profil d'un ami"
+
+#: src/ui/friend_info_widget.ui:62
+msgid "Remove from your friends list"
+msgstr "Supprimer de votre liste d'amis"
+
+#: src/ui/user_info_widget.ui:113 src/ui/friend_info_widget.ui:111
+msgid "Username:"
+msgstr "Nom d'utilisateur:"
+
+#: src/ui/user_info_widget.ui:206 src/ui/friend_info_widget.ui:200
+msgid "Image:"
+msgstr "Image:"
+
+#: src/ui/friend_info_widget.ui:245
+msgid "Last seen:"
+msgstr "Dernière vue:"
+
+#: src/ui/friend_info_widget.ui:290
+msgid "Alias:"
+msgstr "Alias:"
+
+#: src/ui/friend_info_widget.ui:321
+msgid "Set a custom alias to quickly find your friends"
+msgstr "Définir un alias personnalisé pour trouver rapidement vos amis"
+
+#: src/ui/user_info_widget.ui:291 src/ui/friend_info_widget.ui:579
+msgid "Tox"
+msgstr "Tox"
+
+#: src/ui/user_info_widget.ui:330 src/ui/friend_info_widget.ui:612
+msgid "ID:"
+msgstr "ID Tox :"
+
+#: src/ui/message_widget.ui:91
+msgid "Message sent ✓"
+msgstr "Message envoyé ✓"
+
+#: src/ui/message_widget.ui:107
+msgid "Message received ✓"
+msgstr "Message reçu ✓"
+
+#: src/ui/peer_entry.ui:55
+msgid "This peer is also in your friends list"
+msgstr "Ce pair est aussi dans votre liste d'amis"
+
+#: src/ui/settings_widget.ui:38
+msgid "KiB/MiB"
+msgstr "Kb/Mb"
+
+#: src/ui/settings_widget.ui:42
+msgid "KB/MB"
+msgstr "Ko/Mo"
+
+#: src/ui/settings_widget.ui:98
+msgid "General"
+msgstr "Général"
+
+#: src/ui/settings_widget.ui:268
+msgid "Appearance"
+msgstr "Apparence"
+
+#: src/ui/settings_widget.ui:313
+msgid "Dark Theme"
+msgstr "Thème sombre"
+
+#: src/ui/settings_widget.ui:523
+msgid "Minimize to tray"
+msgstr "Réduire au plateau"
+
+#: src/ui/settings_widget.ui:619
+msgid "Privacy"
+msgstr "Vie privée"
+
+#: src/ui/settings_widget.ui:663
+msgid "Send typing notifications"
+msgstr "Envoyer des notifications de frappe"
+
+#: src/ui/settings_widget.ui:676
+msgid "Show others when I am typing"
+msgstr "Afficher les autres lorsque je tape"
+
+#: src/ui/settings_widget.ui:759
+msgid "History"
+msgstr "Histoire"
+
+#: src/ui/settings_widget.ui:893
+msgid "days"
+msgstr "jours"
+
+#: src/ui/settings_widget.ui:923
+msgid "Delete all previous conversations"
+msgstr "Supprimer toutes les conversations précédentes"
+
+#: src/ui/settings_widget.ui:1340
+msgid "Update bootstrap nodes"
+msgstr "Mettre à jour les noeuds bootstrap"
+
+#: src/ui/user_info_widget.ui:79
+msgid "User profile"
+msgstr "Profil de l'utilisateur"
+
+#: src/ui/user_info_widget.ui:372
+msgid "Copy to clipboard"
+msgstr "Copier dans le presse-papier"
+
+#: src/ui/welcome_widget.ui:40
+msgid "A new kind of instant messaging"
+msgstr "Un nouveau type de messagerie instantanée"
+
+#: src/ui/welcome_widget.ui:56
+msgid "Chat with your friends and family without anyone else listening in."
+msgstr "Discutez avec vos amis et votre famille sans que personne d'autre ne vous écoute."
+
+#: src/ui/welcome_widget.ui:109
+msgid "Learn more"
+msgstr "Apprendre encore plus"
+
+#: src/core/Message.vala:76 src/viewmodel/MessageViewModel.vala:87
+#: src/tox/ConferenceMessage.vala:56
+msgid "me"
+msgstr "moi"
+
+#: src/ui/user_info_widget.ui:244
+msgid "Choose an avatar"
+msgstr "Choisissez un avatar"
+
+#: src/ui/friend_request_widget.ui:146
+msgid "Reject request"
+msgstr "Rejeter la demande"
+
+#: src/ui/friend_request_widget.ui:170
+msgid "Accept request"
+msgstr "Accepter la requête"
+
+#: src/ui/application_window.ui:55
+msgid "venom"
+msgstr "venin"
+
+#: src/core/NotificationListener.vala:76
+msgid "New file from %s"
+msgstr "Nouveau fichier de %s"
+
+#: src/viewmodel/ContactListEntryViewModel.vala:58
+msgid "New Message!"
+msgstr "Nouveau message!"
+
+#: src/viewmodel/ContactListEntryViewModel.vala:64
+msgid "Offline"
+msgstr "Hors ligne"
+
+#: src/viewmodel/ContactListEntryViewModel.vala:72
+#: src/ui/user_status_menu.ui:11
+msgid "Away"
+msgstr "Un moyen"
+
+#: src/viewmodel/ContactListEntryViewModel.vala:74
+#: src/ui/user_status_menu.ui:17
+msgid "Busy"
+msgstr "Occupé"
+
+#: src/viewmodel/ContactListEntryViewModel.vala:76 src/ui/user_status_menu.ui:5
+msgid "Online"
+msgstr "En ligne"
+
+#: src/viewmodel/MessageViewModel.vala:65
+msgid "Today at %s"
+msgstr "Aujourd'hui à %s"
+
+#: src/viewmodel/MessageViewModel.vala:69
+msgid "Yesterday at %s"
+msgstr "Hier à %s"
+
+#: src/tox/Conference.vala:43
+msgid "Unnamed conference %u"
+msgstr "Conférence sans nom %u"
+
+#: src/tox/ToxSession.vala:645
+msgid "Address must consist of 76 hexadecimal characters"
+msgstr "L'adresse doit comporter 76 caractères hexadécimaux"
+
+#: src/view/ConversationWindow.vala:102
+msgid "%s is typing..."
+msgstr "%s tape ..."
+
+#: src/view/ConversationWindow.vala:168 src/view/FileTransferEntry.vala:76
+msgid "_Cancel"
+msgstr "_Annuler"
+
+#: src/view/ConversationWindow.vala:169
+msgid "_Open"
+msgstr "_Ouvrir"
+
+#: src/view/FileTransferEntry.vala:77
+msgid "_Save"
+msgstr "_Sauvegarder"
+
+#: src/ui/file_transfer_widget.ui:117
+msgid "No file transfers yet …"
+msgstr "Aucun transfert de fichier pour le moment ..."
+
+#: src/ui/file_transfer_entry.ui:34
+msgid "Remove transfer"
+msgstr "Supprimer le transfert"
+
+#: src/ui/file_transfer_entry.ui:102
+msgid "Open file"
+msgstr "Fichier ouvert"
+
+#: src/ui/file_transfer_entry.ui:126
+msgid "Start transfer"
+msgstr "Démarrer le transfert"
+
+#: src/ui/file_transfer_entry.ui:147
+msgid "Pause transfer"
+msgstr "Suspendre le transfert"
+
+#: src/ui/file_transfer_entry.ui:168
+msgid "Stop transfer"
+msgstr "Arrêter le transfert"
+
+#: src/ui/create_groupchat_widget.ui:199
+msgid "Text"
+msgstr "Texte"
+
+#: src/ui/create_groupchat_widget.ui:214
+msgid "Speech"
+msgstr "Discours"
+
+#: src/ui/peer_entry.ui:68
+msgid "That's you"
+msgstr "C'est toi"
+
+#: src/ui/welcome_widget.ui:156
+msgid "Get involved"
+msgstr "Être impliqué"
+
+#: src/ui/settings_widget.ui:181
+msgid "Proxy"
+msgstr "Procuration"
+
+#: src/ui/settings_widget.ui:326
+msgid "Use a dark variant of the theme"
+msgstr "Utiliser une variante sombre du thème"
+
+#: src/ui/settings_widget.ui:383
+msgid "Animations"
+msgstr "Animations"
+
+#: src/ui/settings_widget.ui:396
+msgid "Enable animated transitions"
+msgstr "Activer les transitions animées"
+
+#: src/ui/settings_widget.ui:453
+msgid "Notifications"
+msgstr "Notifications"
+
+#: src/ui/settings_widget.ui:466
+msgid "Show notifications for unread messages"
+msgstr "Afficher les notifications pour les messages non lus"
+
+#: src/ui/settings_widget.ui:536
+msgid "Minimize app to system tray on close"
+msgstr "Réduire l'application à la barre d'état système à proximité"
+
+#: src/ui/settings_widget.ui:823
+msgid "Keep forever"
+msgstr "Gardez pour toujours"
+
+#: src/ui/settings_widget.ui:860
+msgid "Remove older than"
+msgstr "Retirer plus de"
+
+#: src/ui/settings_widget.ui:1017
+msgid "Connection"
+msgstr "Connexion"
+
+#: src/ui/settings_widget.ui:1060
+msgid "UDP"
+msgstr "UDP"
+
+#: src/ui/settings_widget.ui:1130
+msgid "IPv6"
+msgstr "IPv6"
+
+#: src/ui/settings_widget.ui:1143
+msgid "Allow both IPv4 and IPv6 communication"
+msgstr "Autoriser les communications IPv4 et IPv6"
+
+#: src/ui/settings_widget.ui:1200
+msgid "Local discovery"
+msgstr "Découverte locale"
+
+#: src/ui/settings_widget.ui:1213
+msgid "Look for peers on the local network"
+msgstr "Rechercher des pairs sur le réseau local"
+
+#: src/ui/settings_widget.ui:1270
+msgid "Hole punching"
+msgstr "Perforation"
+
+#: src/ui/settings_widget.ui:1283
+msgid "Enable UDP hole punching"
+msgstr "Activer UDPperforation"
+
+#: src/ui/settings_widget.ui:1376
+msgid "Bootstrap nodes"
+msgstr "Noeuds Bootstrap"
+
+#: src/ui/settings_widget.ui:1511
+msgid "Proxy"
+msgstr "Proxy"
+
+#: src/ui/settings_widget.ui:1578
+msgid "System settings"
+msgstr "Les paramètres du système"
+
+#: src/ui/settings_widget.ui:1591
+msgid "Use your systems proxy settings"
+msgstr "Utilisez les paramètres de proxy de votre système"
+
+#: src/ui/settings_widget.ui:1645
+msgid "Manual settings"
+msgstr "Paramètres manuels"
+
+#: src/ui/settings_widget.ui:1658
+msgid "Use custom proxy settings"
+msgstr "Utiliser les paramètres de proxy personnalisés"
+
+#: src/ui/settings_widget.ui:1699
+msgid "Host"
+msgstr "Hôte"
+
+#: src/ui/settings_widget.ui:1739
+msgid "Set a SOCKS5 proxy to connect to"
+msgstr "Définir un proxy SOCKS5 pour se connecter à"
+
+#: src/ui/friend_info_widget.ui:309
+msgid "Reset alias"
+msgstr "Réinitialiser alias"
+
+#: src/ui/friend_info_widget.ui:428
+msgid "Auto accept conference invites"
+msgstr "Auto accepte les invitations à la conférence"
+
+#: src/ui/friend_info_widget.ui:474
+msgid "Auto accept file transfers"
+msgstr "Auto accepter les transferts de fichiers"
+
+#: src/ui/friend_info_widget.ui:517
+msgid "Save files to"
+msgstr "Enregistrer les fichiers dans"
+
+#: src/viewmodel/ContactListViewModel.vala:102
+msgid "New conference…"
+msgstr ""
+
+#: src/viewmodel/ContactListViewModel.vala:115
+msgid "Invite to conference"
+msgstr ""
+
+#: src/viewmodel/ContactListViewModel.vala:118
+msgid "Show details"
+msgstr ""
+
+#: src/viewmodel/ContactListViewModel.vala:140
+msgid "%u new friend request"
+msgid_plural "%u new friend requests"
+msgstr[0] ""
+msgstr[1] ""
+
+#: src/viewmodel/ContactListViewModel.vala:148
+msgid "%u new conference invite"
+msgid_plural "%u new conference invites"
+msgstr[0] ""
+msgstr[1] ""
+
+#: src/viewmodel/MessageViewModel.vala:51
+msgid "Just now"
+msgstr ""
+
+#: src/viewmodel/MessageViewModel.vala:56
+msgid "%u minute ago"
+msgid_plural "%u minutes ago"
+msgstr[0] ""
+msgstr[1] ""
+
+#: src/viewmodel/MessageViewModel.vala:61
+msgid "%u hour ago"
+msgid_plural "%u hours ago"
+msgstr[0] ""
+msgstr[1] ""
+
+#: src/ui/create_groupchat_widget.ui:59 src/ui/contact_list_widget.ui:350
+msgid "Create a conference"
+msgstr ""
+
+#: src/ui/create_groupchat_widget.ui:147
+msgid "Name the conference (optional)"
+msgstr ""
+
+#: src/ui/create_groupchat_widget.ui:242
+msgid "Select a conference type"
+msgstr ""
+
+#: src/ui/create_groupchat_widget.ui:288
+msgid "New conference"
+msgstr ""
+
+#: src/ui/create_groupchat_widget.ui:301 src/ui/create_groupchat_widget.ui:334
+msgid "Conference invites"
+msgstr ""
+
+#: src/ui/create_groupchat_widget.ui:390
+msgid "No new conference invites"
+msgstr ""
+
+#: src/ui/conversation_window.ui:134
+msgid "Start a video call"
+msgstr ""
+
+#: src/ui/friend_request_widget.ui:44
+msgid "_Public key:"
+msgstr ""
+
+#: src/ui/conference_info_widget.ui:56
+msgid "Leave Conference"
+msgstr ""
+
+#: src/ui/conference_info_widget.ui:174 src/ui/friend_info_widget.ui:357
+msgid "Show notifications"
+msgstr ""
+
+#: src/ui/conference_info_widget.ui:212 src/ui/friend_info_widget.ui:395
+msgid "Notifications have been globally disabled"
+msgstr ""
+
+#: src/ui/conference_invite_entry.ui:43
+msgid "Invite from:"
+msgstr ""
+
+#: src/ui/conference_invite_entry.ui:87
+msgid "Accept invite"
+msgstr ""
+
+#: src/ui/conference_invite_entry.ui:111
+msgid "Reject invite"
+msgstr ""
+
+#: src/ui/add_contact_widget.ui:30
+msgid "No new friend requests"
+msgstr ""
+
+#: src/ui/add_contact_widget.ui:315
+msgid "Add a friend"
+msgstr ""
+
+#: src/ui/add_contact_widget.ui:328 src/ui/add_contact_widget.ui:361
+msgid "Friend requests"
+msgstr ""
+
+#: src/ui/user_info_widget.ui:158 src/ui/friend_info_widget.ui:155
+msgid "Status message:"
+msgstr ""
+
+#: src/ui/settings_widget.ui:1073
+msgid "Use UDP communication when available"
+msgstr ""
+
diff --git a/po/it.po b/po/it.po
index 8065d95..79333f7 100644
--- a/po/it.po
+++ b/po/it.po
@@ -1,1028 +1,635 @@
-# Italian translation for PACKAGE package.
-# Copyright (C) 2014 THE PACKAGE'S COPYRIGHT HOLDER
-# This file is distributed under the same license as the PACKAGE package.
-# Ansa89, 2014.
-#
msgid ""
msgstr ""
-"Project-Id-Version: Venom\n"
-"Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2014-06-17 21:05+0200\n"
-"PO-Revision-Date: 2014-06-17 21:12+0100\n"
-"Last-Translator: Ansa89\n"
-"Language-Team: Italiano\n"
-"Language: it\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
-"X-Generator: Poedit 1.6.5\n"
-
-#: core/ToxSession.vala:725
-#, c-format
-msgid " %s\n"
-msgstr " %s\n"
-
-#: core/DhtNode.vala:47
-msgid " (ipv6)"
-msgstr " (IPv6)"
-
-#: ui/ContactListWindow.vala:627
-#, c-format
-msgid "%F"
-msgstr "%F"
-
-#: core/Message.vala:47
-msgid "%R:%S"
-msgstr "%R:%S"
-
-#: core/GroupChat.vala:52
-#, c-format
-msgid "%i people connected"
-msgstr "%i persone connesse"
-
-#: core/GroupChat.vala:54
-#, c-format
-msgid "%i person connected"
-msgstr "%i persona connessa"
-
-#: core/Contact.vala:69 core/Contact.vala:83
-#, c-format
-msgid "%s (%s)"
-msgstr "%s (%s)"
-
-#: ui/ContactListWindow.vala:648
-#, c-format
-msgid "%s changed his name to %s\n"
-msgstr "%s ha cambiato il suo nome in %s\n"
-
-#: ui/ContactListWindow.vala:652
-#, c-format
-msgid "%s changed his status to %s\n"
-msgstr "%s ha cambiato il suo stato in %s\n"
-
-#: ui/ContactListWindow.vala:663
-#, c-format
-msgid "%s is now %s.\n"
-msgstr "%s ora è %s.\n"
-
-#: ui/ConversationWidget.vala:60
-#, c-format
-msgid "%s is typing..."
-msgstr "%s sta scrivendo..."
-
-#: ui/ContactListWindow.vala:131
-#, c-format
-msgid "%s: %s\n"
-msgstr "%s: %s\n"
-
-#: core/DhtNode.vala:47
-#, c-format
-msgid "%s:%u%s %s"
-msgstr "%s:%u%s %s"
-
-#: ui/ContactListWindow.vala:714
-#, c-format
-msgid "'%s' has invited you to a groupchat, do you want to accept?"
-msgstr "'%s' ti ha invitato in una chat di gruppo. Vuoi accettare?"
-
-#: ui/ContactListWindow.vala:577
-#, c-format
-msgid "* %s"
-msgstr "* %s"
-
-#: ui/ContactListWindow.vala:627
-#, c-format
-msgid "<%i>"
-msgstr "<%i>"
-
-#: ui/ContactListWindow.vala:627
-#, c-format
-msgid "<%s> %s:%s\n"
-msgstr "<%s> %s: %s\n"
-
-#: ui/ConversationWidget.vala:51 ui/GroupConversationWidget.vala:47
-#, c-format
-msgid "%s"
-msgstr "%s"
-
-#: ui/user_info_window.ui:119
-msgid "Tox"
-msgstr "Tox"
-
-#: ui/user_info_window.ui:282
-msgid "User"
-msgstr "Utente"
-
-#: core/Contact.vala:72 core/Contact.vala:86 ui/ConversationView.vala:55
-#, c-format
-msgid "%s"
-msgstr "%s"
-
-#: core/Message.vala:152 core/Message.vala:191
-msgid ""
-msgstr ""
-
-#: ui/AddContactDialog.vala:76
-msgid "Add contact"
-msgstr "Aggiungi contatto"
-
-#: ui/ContactListWindow.vala:617
-#, c-format
-msgid "Added new friend #%i\n"
-msgstr "Aggiunto nuovo amico #%i\n"
-
-#: ui/ContactListWindow.vala:1125 ui/ContactListWindow.vala:1137
-msgid "Adding Friend failed"
-msgstr "Errore durante l'aggiunta del nuovo contattto"
-
-#: ui/ContactListWindow.vala:210
+"X-Generator: POEditor.com\n"
+"Project-Id-Version: Venom\n"
+"Language: it\n"
+"Plural-Forms: nplurals=2; plural=(n != 1);\n"
+
+#: src/core/Application.vala:32
+msgid "Set level of messages to log"
+msgstr "Imposta il livello dei messaggi da registrare"
+
+#: src/core/Application.vala:32
+msgid ""
+msgstr ""
+
+#: src/core/Application.vala:33
+msgid "Display version number"
+msgstr "Visualizza il numero di versione"
+
+#: src/core/NotificationListener.vala:55
+msgid "New message from %s"
+msgstr "Nuovo messaggio da %s"
+
+#: src/core/R.vala:70
+msgid "Tox User"
+msgstr "Utente Tox"
+
+#: src/tox/Conference.vala:47
+msgid "%u Peers online"
+msgstr "%u Peer online"
+
+#: src/view/AboutDialog.vala:53
+msgid "Packagers"
+msgstr "packagers"
+
+#: src/view/AboutDialog.vala:58
+msgid "translator-credits"
+msgstr "Ansa89"
+
+#: src/view/AboutDialog.vala:61
+msgid "Visit us on Github"
+msgstr "Visitaci su Github"
+
+#: src/ui/add_contact_widget.ui:43
+msgid "Please let me add you to my contact list. 😁"
+msgstr ""
+
+#: src/ui/add_contact_widget.ui:99
+msgid "Send a friend request"
+msgstr "Invia una richiesta di amicizia"
+
+#: src/ui/add_contact_widget.ui:133
+msgid "_ID:"
+msgstr "_ID:"
+
+#: src/ui/add_contact_widget.ui:150
+msgid "Enter a Tox ID or URI here"
+msgstr ""
+
+#: src/ui/create_groupchat_widget.ui:113 src/ui/add_contact_widget.ui:154
+msgid "paste from clipboard"
+msgstr ""
+
+#: src/ui/add_contact_widget.ui:188
+msgid "Enter your friends Tox ID"
+msgstr "Inserisci l'ID Tox dei tuoi amici"
+
+#: src/ui/friend_request_widget.ui:78 src/ui/add_contact_widget.ui:220
+msgid "_Message:"
+msgstr ""
+
+#: src/ui/add_contact_widget.ui:246
+msgid "Send a custom message to be displayed to the friend you are adding"
+msgstr "Invia un messaggio personalizzato che sarà visualizzato dal contatto che stai aggiungendo"
+
+#: src/ui/add_contact_widget.ui:268
+msgid "Send your friend a short message"
+msgstr ""
+
+#: src/ui/add_contact_widget.ui:298
+msgid "Send"
+msgstr "Inviare"
+
+#: src/ui/app_menu.ui:7
+msgid "_Preferences"
+msgstr ""
+
+#: src/ui/app_menu.ui:13
+msgid "About"
+msgstr "Di"
+
+#: src/ui/app_menu.ui:17
+msgid "_Quit"
+msgstr "_Smettere"
+
+#: src/ui/create_groupchat_widget.ui:112 src/ui/conference_info_widget.ui:39
+msgid "Conference"
+msgstr ""
+
+#: src/ui/conference_info_widget.ui:105
+msgid "Title:"
+msgstr "Titolo:"
+
+#: src/ui/conference_info_widget.ui:243 src/ui/user_info_widget.ui:449
+#: src/ui/friend_info_widget.ui:666
+msgid "Apply"
+msgstr "Applicare"
+
+#: src/ui/conference_info_widget.ui:261
+msgid "Peers"
+msgstr "Colleghi"
+
+#: src/ui/conference_window.ui:209 src/ui/conversation_window.ui:268
+#: src/ui/user_info_widget.ui:177 src/ui/user_info_widget.ui:178
+msgid "Insert Emoji"
+msgstr ""
+
+#: src/ui/contact_list_widget.ui:216
+msgid "Filter contacts by status"
+msgstr "Filtra i contatti per stato"
+
+#: src/ui/contact_list_widget.ui:222
msgid "All"
msgstr "Tutti"
-#: ui/ContactListWindow.vala:1060 ui/ContactListWindow.vala:1082
-#, c-format
-msgid "Are you sure you want to delete '%s' from your contact list?"
-msgstr "Sei sicuro di voler eliminare '%s' dalla tua lista dei contatti?"
+#: src/ui/contact_list_widget.ui:329
+msgid "Add a contact"
+msgstr ""
-#: core/ToxSession.vala:33
-msgid "Away"
-msgstr "Assente"
+#: src/ui/contact_list_widget.ui:371
+msgid "View file transfers"
+msgstr ""
-#: core/ToxSession.vala:717
-#, c-format
-msgid "Background thread started.\n"
-msgstr "Thread in background avviato.\n"
+#: src/ui/contact_list_widget.ui:392
+msgid "Open preferences"
+msgstr "Preferenze"
-#: core/ToxSession.vala:756
-#, c-format
-msgid "Background thread stopped.\n"
-msgstr "Thread in background fermato.\n"
+#: src/ui/conversation_window.ui:109
+msgid "Start a call"
+msgstr "Inizia una chiamata"
-#: core/Tools.vala:142
-msgid "Bad checksum"
-msgstr "Checksum errato"
+#: src/ui/conversation_window.ui:290
+msgid "Insert attachment"
+msgstr ""
-#: core/ToxSession.vala:35
-msgid "Busy"
-msgstr "Occupato"
+#: src/ui/create_groupchat_widget.ui:93
+msgid "_Title:"
+msgstr "_Titolo:"
-#: ui/conversation_window.ui:156
-msgid "Call contact"
-msgstr "Chiama contatto"
-
-#: ui/conversation_window.ui:174
-msgid "Call contact with video"
-msgstr "Videochiama contatto"
-
-#: core/Tools.vala:158 core/Tools.vala:171
-#, c-format
-msgid "Can't create action regex: %s.\n"
-msgstr "Impossibile creare l'espressione regolare: %s.\n"
-
-#: core/SqliteTools.vala:75
-#, c-format
-msgid "Can't open database: %d: %s\n"
-msgstr "Impossibile accedere al database: %d: %s\n"
-
-#: core/Tools.vala:136
-msgid "Can't send to own key"
-msgstr "Impossibile inviare alla propria chiave"
-
-#: ui/FileTransferChatEntry.vala:119
-msgid "Canceled"
-msgstr "Annullato"
-
-#: ui/contact_list.ui:72
-msgid "Change _Status"
-msgstr "Cambia _Stato"
-
-#: ui/ContactListWindow.vala:670
-msgid "Connected to the network"
-msgstr "Connesso alla rete"
-
-#: core/ToxSession.vala:720
-#, c-format
-msgid "Connecting to DHT Nodes:\n"
-msgstr "Connessione ai server DHT:\n"
-
-#: ui/ContactListWindow.vala:668
-#, c-format
-msgid "Connection to DHT %s.\n"
-msgstr "Connessione al server DHT %s.\n"
-
-#: ui/ContactListWindow.vala:907
-#, c-format
-msgid "Contact accepted file sending request\n"
-msgstr "Il contatto ha accettato la richiesta di invio file\n"
-
-#: ui/ContactListWindow.vala:508
-#, c-format
-msgid "Copied Tox ID to clipboard\n"
-msgstr "Tox ID copiato negli appunti\n"
-
-#: ui/ContactListWindow.vala:1135
-#, c-format
-msgid "Could not add friend: %s.\n"
-msgstr "Impossibile aggiungere il contatto: %s.\n"
-
-#: ui/ContactListWindow.vala:1123
-msgid "Could not add friend: Invalid ID\n"
-msgstr "Impossibile aggiungere il contatto: ID non valido\n"
-
-#: core/SqliteTools.vala:40
-#, c-format
-msgid "Could not bind int to %s."
-msgstr "Impossibile collegare int a %s."
-
-#: core/SqliteTools.vala:50
-#, c-format
-msgid "Could not bind int64 to %s."
-msgstr "Impossibile collegare int64 a %s."
-
-#: core/SqliteTools.vala:60
-#, c-format
-msgid "Could not bind text to %s"
-msgstr "Impossibile collegare text a %s"
-
-#: ui/ContactListWindow.vala:447
-#, c-format
-msgid "Could not change user name!\n"
-msgstr "Impossibile cambiare il nome\n"
-
-#: ui/ContactListWindow.vala:455
-#, c-format
-msgid "Could not change user statusmessage!\n"
-msgstr "Impossibile cambiare lo stato\n"
-
-#: ui/ContactListWindow.vala:1189
-#, c-format
-msgid "Could not create a new groupchat.\n"
-msgstr "Impossibile creare una nuova chat di gruppo.\n"
-
-#: ui/ContactListWindow.vala:725
-#, c-format
-msgid "Could not join groupchat.\n"
-msgstr "Impossibile unirsi alla chat di gruppo.\n"
-
-#: ui/ContactListWindow.vala:146
-#, c-format
-msgid "Could not load session data (%s), creating new one.\n"
-msgstr "Impossibile caricare i dati (%s), ne verranno creati di nuovi.\n"
-
-#: ui/ContactListWindow.vala:130
-#, c-format
-msgid "Could not read theme from \"%s\""
-msgstr "Impossibile leggere il tema da \"%s\""
-
-#: ui/ContactListWindow.vala:1090
-#, c-format
-msgid "Could not remove %s.\n"
-msgstr "Impossibile rimuovere %s.\n"
-
-#: ui/ContactListWindow.vala:1068
-#, c-format
-msgid "Could not remove contact %i.\n"
-msgstr "Impossibile rimuovere il contatto %i.\n"
-
-#: core/ToxSession.vala:352
-#, c-format
-msgid "Could not remove peer [%i] from groupchat #%i (no such peer)\n"
+#: src/ui/create_groupchat_widget.ui:179
+msgid "T_ype:"
+msgstr "Genere:"
+
+#: src/ui/create_groupchat_widget.ui:271
+msgid "Create"
+msgstr "Creare"
+
+#: src/ui/file_transfer_widget.ui:35
+msgid "File transfers"
msgstr ""
-"Impossibile rimuovere il peer [%i] dalla chat di gruppo #%i (peer non "
-"trovato)\n"
-
-#: ui/ContactListWindow.vala:1112
-msgid "Could not resolve ID from DNS record\n"
-msgstr "Impossibile risolvere il Tox ID dal record DNS\n"
-
-#: ui/contact_list.ui:416
-msgid "Create groupchat"
-msgstr "Crea chat di gruppo"
-
-#: ui/settings_window.ui:301
-msgid "Default Tox DNS ID suffix:"
-msgstr "Suffisso di default per i Tox DNS ID:"
-
-#: ui/FileTransferChatEntry.vala:125 ui/FileTransferChatEntry.vala:129
-msgid "Disconnected"
-msgstr "Disconnesso"
-
-#: ui/ContactListWindow.vala:673
-msgid "Disconnected from the network"
-msgstr "Disconnesso dalla rete"
-
-#: ui/UserInfoWindow.vala:86
-msgid "Edit user information"
-msgstr "Modifica informazioni utente"
-
-#: ui/ContactListWindow.vala:899
-#, c-format
-msgid "Ended file transfer for %s to %s\n"
-msgstr "Trasferimento file finito per %s a %s\n"
-
-#: ui/ContactListWindow.vala:102
-#, c-format
-msgid "Ending session...\n"
-msgstr "Chiudendo la sessione...\n"
-
-#: ui/add_contact_dialog.ui:40
-msgid "Enter a Tox ID here or a Tox URI"
-msgstr "Inserisci un Tox ID o un Tox URI"
-
-#: core/ContactStorage.vala:108
-#, c-format
-msgid "Error creating contacts insert statement: %d: %s\n"
-msgstr "Errore nel creare lo statement di inserimento contatti: %d: %s\n"
-
-#: core/ContactStorage.vala:113
-#, c-format
-msgid "Error creating contacts select statement: %d: %s\n"
-msgstr "Errore nel creare lo statement di selezione contatti: %d: %s\n"
-
-#: core/ContactStorage.vala:103
-#, c-format
-msgid "Error creating contacts table: %s\n"
-msgstr "Errore nel creare la tabella dei contatti: %s\n"
-
-#: core/DhtNodeStorage.vala:177
-#, c-format
-msgid "Error creating dht nodes insert statement: %d: %s\n"
-msgstr "Errore nel creare lo statement di inserimento server DHT: %d: %s\n"
-
-#: core/DhtNodeStorage.vala:182
-#, c-format
-msgid "Error creating dht nodes select statement: %d: %s\n"
-msgstr "Errore nel create lo statement di selezione server DHT: %d: %s\n"
-
-#: core/DhtNodeStorage.vala:172
-#, c-format
-msgid "Error creating dht nodes table: %s\n"
-msgstr "Errore nel creare la tabella dei server DHT: %s\n"
-
-#: core/ToxDns.vala:36
-#, c-format
-msgid "Error creating tox dns regex: %s\n"
-msgstr "Errore nel creare l'espressione regolare dei DNS tox: %s\n"
-
-#: core/ToxDns.vala:51
-#, c-format
-msgid "Error creating tox uri regex: %s\n"
-msgstr "Errore nel creare l'espressione regolare degli URI tox: %s\n"
-
-#: ui/ConversationTextView.vala:184
-#, c-format
-msgid "Error matching uri regex: %s\n"
-msgstr "Errore nel match dell'espressione regolare degli URI: %s\n"
-
-#: ui/ConversationWidget.vala:308
-#, c-format
-msgid "Error occured while getting file size: %s"
-msgstr "Errore nel calcolare la dimesione del file: %s"
-
-#: core/ToxSession.vala:111
-#, c-format
-msgid "Error opening database: %s\n"
-msgstr "Errore nell'accedere al database: %s\n"
-
-#: core/Settings.vala:112
-#, c-format
-msgid "Error reading configs:%s\n"
-msgstr "Errore nella lettura delle configurazioni: %s\n"
-
-#: core/ToxDns.vala:81
-#, c-format
-msgid "Error resolving name: %s\n"
-msgstr "Errore nel risolvere il nome: %s\n"
-
-#: core/MessageLog.vala:135
-#, c-format
-msgid "Error retrieving logs from sqlite database: %s\n"
-msgstr "Errore nel recupero dei log dal database sqlite: %s\n"
-
-#: core/Settings.vala:99
-#, c-format
-msgid "Error saving configs:%s\n"
-msgstr "Errore nel salvataggio delle configurazioni: %s\n"
-
-#: core/Tools.vala:123
-#, c-format
-msgid "Error when doing uri markup: %s"
-msgstr "Errore durante il markup dell'URI: %s"
-
-#: ui/ConversationTextView.vala:245
-#, c-format
-msgid "Error when showing uri: %s\n"
-msgstr "Errore nel mostrare l'URI: %s\n"
-
-#: ui/ContactListWindow.vala:168
-#, c-format
-msgid "Error while loading icon: %s\n"
-msgstr "Errore nel caricare l'icona: %s\n"
-
-#: core/ResourceFactory.vala:126
-#, c-format
-msgid "Error while loading image from \"%s\":%s\n"
-msgstr "Errore nel caricamento dell'immagine da \"%s\": %s\n"
-
-#: core/ToxSession.vala:801
-msgid "Error while loading messenger data."
-msgstr "Errore nel caricamento dei dati del messenger."
-
-#: core/ToxSession.vala:795
-msgid "Error while reading from stream."
-msgstr "Errore nel leggere lo stream."
-
-#: ui/FileTransferChatEntry.vala:171
-#, c-format
-msgid "Error while trying to create file: %s\n"
-msgstr "Errore nel creare il file: %s\n"
-
-#: ui/ContactListWindow.vala:961
-#, c-format
-msgid "Error while trying to write data to file\n"
-msgstr "Errore nella scrittura dei dati su file\n"
-
-#: core/ToxSession.vala:828
-msgid "Error while writing to stream."
-msgstr "Errore nella scrittura dello stream."
-
-#: core/ContactStorage.vala:88
-#, c-format
-msgid "Error writing contact to sqlite database: %s\n"
-msgstr "Errore nella scrittura del contatto nel database sqlite: %s\n"
-
-#: core/MessageLog.vala:118
-#, c-format
-msgid "Error writing message to sqlite database: %s\n"
-msgstr "Errore nella scrittura del messaggio nel database sqlite: %s\n"
-
-#: core/MessageLog.vala:186 core/MessageLog.vala:193
-#, c-format
-msgid "Error: %d: %s\n"
-msgstr "Errore: %d: %s\n"
-
-#: core/MessageLog.vala:169 core/MessageLog.vala:179
-#: ui/ConversationView.vala:78
-#, c-format
-msgid "Error: %s\n"
-msgstr "Errore %s\n"
-
-#: core/ToxSession.vala:788
-#, c-format
-msgid "File \"%d\" does not exist."
-msgstr "Il file \"%d\" non esiste."
-
-#: ui/ContactListWindow.vala:929
-#, c-format
-msgid "File transfer finished for file number %u"
-msgstr "Trasferimento file finito per il file numero %u"
-
-#: ui/ContactListWindow.vala:925
-#, c-format
-msgid "File transfer was rejected for file number %u"
-msgstr "Trasferimento file rifiutato per il file numero %u"
-
-#: ui/FileTransferChatEntry.vala:94
-msgid "File was rejected"
-msgstr "Il file è stato rifiutato"
-
-#: ui/settings_window.ui:236
-msgid "Flash window when a new message arrives"
-msgstr "Illumina finestra quando arriva un nuovo messaggio"
-
-#: ui/ContactListWindow.vala:614
-#, c-format
-msgid "Friend could not be added.\n"
-msgstr "Il contatto non può essere aggiunto.\n"
-
-#: core/Tools.vala:138
-msgid "Friend request already sent"
-msgstr "Richiesta d'amicizia già inviata"
-
-#: core/Tools.vala:148
-msgid "Friend request successfully sent"
-msgstr "Richiesta d'amicizia inviata con successo"
-
-#: ui/ContactListWindow.vala:1142
-#, c-format
-msgid "Friend request successfully sent. Friend added as %i.\n"
+
+#: src/ui/friend_info_widget.ui:45
+msgid "Friend profile"
msgstr ""
-"Richiesta d'amicizia inviata con successo. Contatto aggiunto come %i.\n"
-
-#: ui/ContactListWindow.vala:771
-#, c-format
-msgid "Group action from unknown contact #%i [%i]\n"
-msgstr "Azione di gruppo da contatto sconosciuto #%i [%i]\n"
-
-#: ui/ContactListWindow.vala:708
-#, c-format
-msgid "Group invite from %s with public key %s\n"
-msgstr "Invito di gruppo da %s con chiave pubblica %s\n"
-
-#: ui/ContactListWindow.vala:742
-#, c-format
-msgid "Group message from unknown contact #%i [%i]\n"
-msgstr "Messaggio di gruppo da contatto sconosciuto #%i [%i]\n"
-
-#: core/GroupChat.vala:45
-#, c-format
-msgid "Groupchat #%i"
-msgstr "Chat di gruppo #%i"
-
-#: ui/ContactListWindow.vala:896
-#, c-format
-msgid "I/O error while trying to close file stream: %s\n"
-msgstr "Errore I/O nella chiusura del file di stream: %s\n"
-
-#: ui/ContactListWindow.vala:888
-#, c-format
-msgid "I/O error while trying to read file: %s\n"
-msgstr "Errore I/O nel leggere il file: %s\n"
-
-#: ui/AddContactDialog.vala:96
-msgid "ID contains invalid characters"
-msgstr "Il Tox ID contiene caratteri non validi"
-
-#: ui/user_info_window.ui:40
-msgid "ID:"
-msgstr "Tox ID:"
-#: ui/ContactListWindow.vala:86
-#, c-format
-msgid "ID: %s\n"
-msgstr "Tox ID: %s\n"
+#: src/ui/friend_info_widget.ui:62
+msgid "Remove from your friends list"
+msgstr "Rimuovi dalla tua lista amici"
-#: ui/user_info_window.ui:222
-msgid "Icon:"
-msgstr "Icona:"
+#: src/ui/user_info_widget.ui:113 src/ui/friend_info_widget.ui:111
+msgid "Username:"
+msgstr "Nome utente:"
-#: core/SqliteTools.vala:37 core/SqliteTools.vala:47 core/SqliteTools.vala:57
-#, c-format
-msgid "Index for %s not found."
-msgstr "Indice per %s non trovato."
+#: src/ui/user_info_widget.ui:206 src/ui/friend_info_widget.ui:200
+msgid "Image:"
+msgstr "Immagine:"
-#: ui/conversation_window.ui:290
-msgid "Insert Smiley"
-msgstr "Inserisci emoticon"
+#: src/ui/friend_info_widget.ui:245
+msgid "Last seen:"
+msgstr ""
-#: core/ToxDns.vala:113
-#, c-format
-msgid "Invalid record\n"
-msgstr "Record DNS non valido\n"
+#: src/ui/friend_info_widget.ui:290
+msgid "Alias:"
+msgstr "Alias:"
-#: core/ToxDns.vala:64
-#, c-format
-msgid "Invalid tox uri\n"
-msgstr "Tox URI non valido\n"
+#: src/ui/friend_info_widget.ui:321
+msgid "Set a custom alias to quickly find your friends"
+msgstr "Imposta un alias personalizzato per trovare rapidamente i tuoi amici"
-#: ui/ContactListWindow.vala:728
-#, c-format
-msgid "Joined Groupchat #%i\n"
-msgstr "Entrato nella chat di gruppo #%i\n"
+#: src/ui/user_info_widget.ui:291 src/ui/friend_info_widget.ui:579
+msgid "Tox"
+msgstr "Tox"
-#: ui/settings_window.ui:18
-msgid "KB/MB"
-msgstr "KB/MB"
+#: src/ui/user_info_widget.ui:330 src/ui/friend_info_widget.ui:612
+msgid "ID:"
+msgstr "Tox ID:"
+
+#: src/ui/message_widget.ui:91
+msgid "Message sent ✓"
+msgstr ""
+
+#: src/ui/message_widget.ui:107
+msgid "Message received ✓"
+msgstr ""
-#: ui/settings_window.ui:78
-msgid "Keep history"
-msgstr "Salva cronologia delle chat"
+#: src/ui/peer_entry.ui:55
+msgid "This peer is also in your friends list"
+msgstr "Questo peer è anche nella tua lista amici"
-#: ui/settings_window.ui:14
+#: src/ui/settings_widget.ui:38
msgid "KiB/MiB"
msgstr "KiB/MiB"
-#: core/Contact.vala:117
-#, c-format
-msgid "Last seen: %s"
-msgstr "Visto l'ultima volta: %s"
+#: src/ui/settings_widget.ui:42
+msgid "KB/MB"
+msgstr "KB/MB"
-#: ui/AddContactDialog.vala:53
-#, c-format
-msgid "Loading add contact window failed!\n"
-msgstr "Caricamento della finestra di aggiunta contatti fallito\n"
+#: src/ui/settings_widget.ui:98
+msgid "General"
+msgstr "Generale"
-#: ui/ConversationWidget.vala:71 ui/SettingsWindow.vala:32
-#, c-format
-msgid "Loading conversation window failed!\n"
-msgstr "Caricamento della finestra di conversazione fallito\n"
+#: src/ui/settings_widget.ui:268
+msgid "Appearance"
+msgstr "Aspetto"
-#: ui/FileTransferChatEntry.vala:40
-#, c-format
-msgid "Loading message widget failed!\n"
-msgstr "Caricamento del widget dei messaggi fallito\n"
+#: src/ui/settings_widget.ui:313
+msgid "Dark Theme"
+msgstr "Tema scuro"
-#: core/Tools.vala:132
-msgid "Message too long"
-msgstr "Messaggio troppo lungo"
+#: src/ui/settings_widget.ui:523
+msgid "Minimize to tray"
+msgstr "Riduci a icona sul vassoio"
-#: ui/settings_window.ui:337
-msgid "Miscellaneous"
-msgstr "Altro"
+#: src/ui/settings_widget.ui:619
+msgid "Privacy"
+msgstr "Privacy"
-#: ui/user_info_window.ui:192
-msgid "Name:"
-msgstr "Nome:"
+#: src/ui/settings_widget.ui:663
+msgid "Send typing notifications"
+msgstr ""
-#: ui/ContactListWindow.vala:604
-#, c-format
-msgid ""
-"New friend request from '%s'.\n"
-"Do you want to accept?"
+#: src/ui/settings_widget.ui:676
+msgid "Show others when I am typing"
+msgstr ""
+
+#: src/ui/settings_widget.ui:759
+msgid "History"
msgstr ""
-"Nuova richiesta d'amicizia da '%s'.\n"
-"Vuoi accettarla?"
-#: ui/AddContactDialog.vala:90
-msgid "No ID given"
-msgstr "Nessun Tox ID inserito"
+#: src/ui/settings_widget.ui:893
+msgid "days"
+msgstr "giorni"
+
+#: src/ui/settings_widget.ui:923
+msgid "Delete all previous conversations"
+msgstr "Elimina tutte le conversazioni precedenti"
+
+#: src/ui/settings_widget.ui:1340
+msgid "Update bootstrap nodes"
+msgstr "Aggiorna nodi di bootstrap"
+
+#: src/ui/user_info_widget.ui:79
+msgid "User profile"
+msgstr "Profilo utente"
+
+#: src/ui/user_info_widget.ui:372
+msgid "Copy to clipboard"
+msgstr ""
+
+#: src/ui/welcome_widget.ui:40
+msgid "A new kind of instant messaging"
+msgstr "Un nuovo tipo di messaggistica istantanea"
+
+#: src/ui/welcome_widget.ui:56
+msgid "Chat with your friends and family without anyone else listening in."
+msgstr "Chatta con i tuoi amici e familiari senza che nessun altro ascolti."
+
+#: src/ui/welcome_widget.ui:109
+msgid "Learn more"
+msgstr "Per saperne di più"
+
+#: src/core/Message.vala:76 src/viewmodel/MessageViewModel.vala:87
+#: src/tox/ConferenceMessage.vala:56
+msgid "me"
+msgstr "me"
-#: core/Tools.vala:134
-msgid "No message included"
-msgstr "Nessun messaggio incluso"
+#: src/ui/user_info_widget.ui:244
+msgid "Choose an avatar"
+msgstr "Scegli un avatar"
-#: core/ToxDns.vala:103
-#, c-format
-msgid "No pin privided, aborting...\n"
-msgstr "Nessun PIN inserito, annullo...\n"
+#: src/ui/friend_request_widget.ui:146
+msgid "Reject request"
+msgstr "Rifiuta richiesta"
-#: ui/contact_list.ui:118
-msgid "O_ffline"
-msgstr "O_ffline"
+#: src/ui/friend_request_widget.ui:170
+msgid "Accept request"
+msgstr "Richiesta accettata"
-#: core/Contact.vala:98 core/Contact.vala:108 core/ToxSession.vala:37
+#: src/ui/application_window.ui:55
+msgid "venom"
+msgstr "veleno"
+
+#: src/core/NotificationListener.vala:76
+msgid "New file from %s"
+msgstr "Nuovo file da %s"
+
+#: src/viewmodel/ContactListEntryViewModel.vala:58
+msgid "New Message!"
+msgstr "Nuovo messaggio!"
+
+#: src/viewmodel/ContactListEntryViewModel.vala:64
msgid "Offline"
-msgstr "Offline"
+msgstr "disconnesso"
-#: core/GroupChatContact.vala:32 core/ToxSession.vala:31
-#: ui/ContactListWindow.vala:208
+#: src/viewmodel/ContactListEntryViewModel.vala:72
+#: src/ui/user_status_menu.ui:11
+msgid "Away"
+msgstr "Lontano"
+
+#: src/viewmodel/ContactListEntryViewModel.vala:74
+#: src/ui/user_status_menu.ui:17
+msgid "Busy"
+msgstr "Occupato"
+
+#: src/viewmodel/ContactListEntryViewModel.vala:76 src/ui/user_status_menu.ui:5
msgid "Online"
-msgstr "Online"
+msgstr "in linea"
-#: ui/contact_list.ui:449
-msgid "Open preferences"
-msgstr "Preferenze"
+#: src/viewmodel/MessageViewModel.vala:65
+msgid "Today at %s"
+msgstr "Oggi a %s"
-#: core/Tools.vala:146
-msgid "Out of memory"
-msgstr "Memoria esaurita"
+#: src/viewmodel/MessageViewModel.vala:69
+msgid "Yesterday at %s"
+msgstr "Ieri a %s"
-#: ui/FileTransferChatEntry.vala:104
-msgid "Paused"
-msgstr "In pausa"
+#: src/tox/Conference.vala:43
+msgid "Unnamed conference %u"
+msgstr "Conferenza senza nome %u"
-#: ui/PinDialog.vala:37
-#, c-format
-msgid ""
-"Please insert PIN for \n"
-"%s"
+#: src/tox/ToxSession.vala:645
+msgid "Address must consist of 76 hexadecimal characters"
+msgstr "L'indirizzo deve essere composto da 76 caratteri esadecimali"
+
+#: src/view/ConversationWindow.vala:102
+msgid "%s is typing..."
+msgstr "%s sta scrivendo ..."
+
+#: src/view/ConversationWindow.vala:168 src/view/FileTransferEntry.vala:76
+msgid "_Cancel"
+msgstr "_Annulla"
+
+#: src/view/ConversationWindow.vala:169
+msgid "_Open"
+msgstr "_Aperto"
+
+#: src/view/FileTransferEntry.vala:77
+msgid "_Save"
+msgstr "_Salvare"
+
+#: src/ui/file_transfer_widget.ui:117
+msgid "No file transfers yet …"
+msgstr "Nessun trasferimento di file ancora ..."
+
+#: src/ui/file_transfer_entry.ui:34
+msgid "Remove transfer"
+msgstr "Rimuovi trasferimento"
+
+#: src/ui/file_transfer_entry.ui:102
+msgid "Open file"
+msgstr "Apri il file"
+
+#: src/ui/file_transfer_entry.ui:126
+msgid "Start transfer"
+msgstr "Avvia trasferimento"
+
+#: src/ui/file_transfer_entry.ui:147
+msgid "Pause transfer"
+msgstr "Metti in pausa il trasferimento"
+
+#: src/ui/file_transfer_entry.ui:168
+msgid "Stop transfer"
+msgstr "Interrompere il trasferimento"
+
+#: src/ui/create_groupchat_widget.ui:199
+msgid "Text"
+msgstr "Testo"
+
+#: src/ui/create_groupchat_widget.ui:214
+msgid "Speech"
+msgstr "Discorso"
+
+#: src/ui/peer_entry.ui:68
+msgid "That's you"
+msgstr "Sei tu"
+
+#: src/ui/welcome_widget.ui:156
+msgid "Get involved"
+msgstr "Mettersi in gioco"
+
+#: src/ui/settings_widget.ui:181
+msgid "Proxy"
+msgstr "delega"
+
+#: src/ui/settings_widget.ui:326
+msgid "Use a dark variant of the theme"
+msgstr "Utilizza una variante scura del tema"
+
+#: src/ui/settings_widget.ui:383
+msgid "Animations"
+msgstr "animazioni"
+
+#: src/ui/settings_widget.ui:396
+msgid "Enable animated transitions"
msgstr ""
-"Per favore inserisci il PIN per \n"
-"%s"
-#: ui/PinDialog.vala:49
-msgid "Please insert PIN..."
-msgstr "Per favore inserisci il PIN..."
+#: src/ui/settings_widget.ui:453
+msgid "Notifications"
+msgstr "notifiche"
-#: ui/add_contact_dialog.ui:6
-msgid "Please let me add you to my contact list."
-msgstr "Per favore permettimi di aggiungerti alla mia lista contatti."
+#: src/ui/settings_widget.ui:466
+msgid "Show notifications for unread messages"
+msgstr ""
-#: ui/settings_window.ui:221
-msgid "Privacy"
-msgstr "Privacy"
+#: src/ui/settings_widget.ui:536
+msgid "Minimize app to system tray on close"
+msgstr ""
+
+#: src/ui/settings_widget.ui:823
+msgid "Keep forever"
+msgstr "Mantieni per sempre"
-#: ui/ContactListWindow.vala:869
-#, c-format
-msgid "Read incorrect number of bytes from file\n"
-msgstr "Letto un numero non corretto di bytes dal file\n"
+#: src/ui/settings_widget.ui:860
+msgid "Remove older than"
+msgstr "Rimuovi più vecchio di"
-#: ui/FileTransferChatEntry.vala:113
-msgid "Receiving failed"
-msgstr "Ricezione fallita"
+#: src/ui/settings_widget.ui:1017
+msgid "Connection"
+msgstr ""
-#: ui/ContactListWindow.vala:1114
-msgid "Resolving ID failed"
-msgstr "Risoluzione del Tox ID fallita"
+#: src/ui/settings_widget.ui:1060
+msgid "UDP"
+msgstr "UDP"
-#: ui/ContactListWindow.vala:427
-#, c-format
-msgid "Retrieved contact %s from savefile.\n"
-msgstr "Recupero contatto %s dal savefile.\n"
+#: src/ui/settings_widget.ui:1130
+msgid "IPv6"
+msgstr "IPv6"
-#: Main.vala:50
-#, c-format
-msgid "Run '%s --help' to see a full list of available command line options.\n"
+#: src/ui/settings_widget.ui:1143
+msgid "Allow both IPv4 and IPv6 communication"
msgstr ""
-"Esegui '%s --help' per vedere la lista completa delle opzioni disponibili.\n"
-
-#: core/MessageLog.vala:86
-#, c-format
-msgid "SQLite database closed.\n"
-msgstr "Database SQLita chiuso.\n"
-
-#: core/MessageLog.vala:82
-#, c-format
-msgid "SQLite database created.\n"
-msgstr "Database SQLite creato.\n"
-
-#: ui/FileTransferChatEntry.vala:158
-msgid "Save"
-msgstr "Salva"
-
-#: ui/FileTransferChatEntry.vala:155
-msgid "Save file"
-msgstr "Salva file"
-
-#: ui/ContactListWindow.vala:120
-#, c-format
-msgid "Saving session file failed: %s\n"
-msgstr "Salvataggio del file di sessione fallito: %s\n"
-
-#: ui/FileTransferChatEntry.vala:165
-#, c-format
-msgid "Saving to: %s\n"
-msgstr "Salvataggio in: %s\n"
-
-#: ui/ContactListWindow.vala:116
-#, c-format
-msgid "Saving tox session data\n"
-msgstr "Salvataggio dei dati di sessione\n"
-
-#: ui/ConversationWidget.vala:282
-msgid "Select"
-msgstr "Seleziona"
-
-#: ui/ConversationWidget.vala:279
-msgid "Select a file to send"
-msgstr "Seleziona un file da inviare"
-
-#: ui/add_contact_dialog.ui:113
-msgid "Send a custom message to be displayed to the friend you are adding"
+
+#: src/ui/settings_widget.ui:1200
+msgid "Local discovery"
+msgstr "Scoperta locale"
+
+#: src/ui/settings_widget.ui:1213
+msgid "Look for peers on the local network"
+msgstr ""
+
+#: src/ui/settings_widget.ui:1270
+msgid "Hole punching"
+msgstr "Perforazione"
+
+#: src/ui/settings_widget.ui:1283
+msgid "Enable UDP hole punching"
+msgstr ""
+
+#: src/ui/settings_widget.ui:1376
+msgid "Bootstrap nodes"
msgstr ""
-"Invia un messaggio personalizzato che sarà visualizzato dal contatto che "
-"stai aggiungendo"
-#: ui/conversation_window.ui:308
-msgid "Send file"
-msgstr "Invia file"
+#: src/ui/settings_widget.ui:1511
+msgid "Proxy"
+msgstr ""
-#: ui/conversation_window.ui:341
-msgid "Send message"
-msgstr "Invia messaggio"
+#: src/ui/settings_widget.ui:1578
+msgid "System settings"
+msgstr "Impostazioni di sistema"
-#: ui/FileTransferChatEntry.vala:107
-msgid "Sending failed"
-msgstr "Invio fallito"
+#: src/ui/settings_widget.ui:1591
+msgid "Use your systems proxy settings"
+msgstr ""
-#: ui/ContactListWindow.vala:111
-#, c-format
-msgid "Session ended gracefully.\n"
-msgstr "Sessione terminata senza errori.\n"
+#: src/ui/settings_widget.ui:1645
+msgid "Manual settings"
+msgstr "Impostazioni manuali"
-#: ui/add_contact_dialog.ui:67
-msgid "Set a custom nickname for the friend you are about to add"
+#: src/ui/settings_widget.ui:1658
+msgid "Use custom proxy settings"
msgstr ""
-"Imposta un nickname personalizzato per il contatto che stai aggiungendo"
-#: core/Tools.vala:144
-msgid "Set new nospam"
-msgstr "Imposta un nuovo valore nospam"
+#: src/ui/settings_widget.ui:1699
+msgid "Host"
+msgstr "Ospite"
-#: ui/settings_window.ui:30
-msgid "Settings"
-msgstr "Impostazioni"
+#: src/ui/settings_widget.ui:1739
+msgid "Set a SOCKS5 proxy to connect to"
+msgstr ""
-#: core/Settings.vala:102
-#, c-format
-msgid "Settings saved.\n"
-msgstr "Impostazioni salvate.\n"
+#: src/ui/friend_info_widget.ui:309
+msgid "Reset alias"
+msgstr "Reimposta l'alias"
-#: ui/settings_window.ui:186
-msgid "Show _others when I am typing"
-msgstr "Mostra agli altri quando sto scrivendo"
+#: src/ui/friend_info_widget.ui:428
+msgid "Auto accept conference invites"
+msgstr "Accetta automaticamente gli inviti alla conferenza"
-#: ui/settings_window.ui:258
-msgid "Show filesize in"
-msgstr "Mostra dimensione file in"
+#: src/ui/friend_info_widget.ui:474
+msgid "Auto accept file transfers"
+msgstr "Accetta automaticamente i trasferimenti di file"
-#: ui/settings_window.ui:202
-msgid "Show me when others are typing"
-msgstr "Mostra quando gli altri stanno scrivendo"
+#: src/ui/friend_info_widget.ui:517
+msgid "Save files to"
+msgstr "Salva i file in"
-#: Main.vala:70
-#, c-format
-msgid "Starting in offline mode\n"
-msgstr "Avvio in modalità offline\n"
+#: src/viewmodel/ContactListViewModel.vala:102
+msgid "New conference…"
+msgstr ""
-#: ui/user_info_window.ui:178
-msgid "Status message:"
-msgstr "Messaggio di stato:"
+#: src/viewmodel/ContactListViewModel.vala:115
+msgid "Invite to conference"
+msgstr ""
-#: ui/ContactListWindow.vala:408
-#, c-format
-msgid "Theme refreshed\n"
-msgstr "Tema ricaricato\n"
+#: src/viewmodel/ContactListViewModel.vala:118
+msgid "Show details"
+msgstr ""
-#: ui/Client.vala:116
-msgid "There is currently no help available"
-msgstr "Attualmente non è disponibile una pagina di aiuto"
+#: src/viewmodel/ContactListViewModel.vala:140
+msgid "%u new friend request"
+msgid_plural "%u new friend requests"
+msgstr[0] ""
+msgstr[1] ""
-#: core/ResourceFactory.vala:77
-msgid "Tox User"
-msgstr "Utente Tox"
+#: src/viewmodel/ContactListViewModel.vala:148
+msgid "%u new conference invite"
+msgid_plural "%u new conference invites"
+msgstr[0] ""
+msgstr[1] ""
-#: core/ResourceFactory.vala:78
-#, c-format
-msgid "Toxing on Venom v.%s"
-msgstr "Toxing on Venom v.%s"
-
-#: ui/ContactListWindow.vala:826
-#, c-format
-msgid "Trying to send unknown file"
-msgstr "Cercando di inviare un file sconosciuto"
-
-#: ui/MessageTextView.vala:27
-msgid "Type your message here..."
-msgstr "Scrivi il tuo messaggio qui..."
-
-#: core/Tools.vala:140
-msgid "Unknown error"
-msgstr "Errore sconosciuto"
-
-#: ui/ContactListWindow.vala:890
-#, c-format
-msgid "Unknown error while trying to read file: %s\n"
-msgstr "Errore sconosciuto nel leggere il file: %s\n"
-
-#: Main.vala:65
-#, c-format
-msgid "Using Gtk.TextView to display messages\n"
-msgstr "Uso Gtk.TextView per visualizzare i messaggi\n"
-
-#: Main.vala:60
-#, c-format
-msgid "Using data file \"%s\"\n"
-msgstr "Uso il datafile \"%s\"\n"
-
-#: ui/AddContactDialog.vala:100
-msgid "Valid ID size"
-msgstr "Dimensione Tox ID valida"
-
-#: ui/ContactListWindow.vala:461
-#, c-format
-msgid "Venom (%s)"
-msgstr "Venom (%s)"
-
-#: ui/ConversationTextView.vala:139
-#, c-format
-msgid "[%s] "
-msgstr "[%s] "
-
-#: ui/ContactListWindow.vala:638
-#, c-format
-msgid "[ac] %i:%s\n"
-msgstr "[ac] %i: %s\n"
-
-#: ui/ContactListWindow.vala:598
-#, c-format
-msgid "[fr] %s:%s\n"
-msgstr "[fr] %s: %s\n"
-
-#: ui/ContactListWindow.vala:763
-#, c-format
-msgid "[ga] %s [%i]@%i: %s\n"
-msgstr "[ga] %s [%i]@%i: %s\n"
-
-#: ui/ContactListWindow.vala:734
-#, c-format
-msgid "[gm] %s [%i]@%i: %s\n"
-msgstr "[gm] %s [%i]@%i: %s\n"
-
-#: ui/ContactListWindow.vala:660
-#, c-format
-msgid "[rr] %s:%u\n"
-msgstr "[rr] %s: %u\n"
-
-#: ui/ContactListWindow.vala:656
-#, c-format
-msgid "[us] %s:%i\n"
-msgstr "[us] %s: %i\n"
-
-#: ui/contact_list.ui:96
-msgid "_Away"
-msgstr "_Assente"
-
-#: ui/user_info_window.ui:254
-msgid "_Browse..."
-msgstr "_Sfoglia..."
-
-#: ui/contact_list.ui:107
-msgid "_Busy"
-msgstr "_Occupato"
-
-#: ui/contact_list.ui:61
-msgid "_Copy ID to clipboard"
-msgstr "_Copia Tox ID negli appunti"
-
-#: ui/contact_list.ui:50
-msgid "_Edit user"
-msgstr "_Modifica utente"
-
-#: ui/add_contact_dialog.ui:94
-msgid "_Message (optional):"
-msgstr "_Messaggio (opzionale):"
-
-#: ui/add_contact_dialog.ui:54
-msgid "_Nickname (optional):"
-msgstr "_Nickname (opzionale):"
-
-#: ui/contact_list.ui:85
-msgid "_Online"
-msgstr "_Online"
-
-#: ui/add_contact_dialog.ui:27
-msgid "_Tox ID:"
-msgstr "_Tox ID:"
-
-#: ui/contact_list.ui:278
-msgid "connecting..."
-msgstr "connessione..."
-
-#: ui/settings_window.ui:160
-msgid "days"
-msgstr "giorni"
+#: src/viewmodel/MessageViewModel.vala:51
+msgid "Just now"
+msgstr ""
-#: ui/settings_window.ui:127
-msgid "delete after"
-msgstr "elimina dopo"
+#: src/viewmodel/MessageViewModel.vala:56
+msgid "%u minute ago"
+msgid_plural "%u minutes ago"
+msgstr[0] ""
+msgstr[1] ""
-#: Main.vala:49
-#, c-format
-msgid "error: %s\n"
-msgstr "errore: %s\n"
+#: src/viewmodel/MessageViewModel.vala:61
+msgid "%u hour ago"
+msgid_plural "%u hours ago"
+msgstr[0] ""
+msgstr[1] ""
-#: ui/ContactListWindow.vala:668
-msgid "established"
-msgstr "stabilita"
+#: src/ui/create_groupchat_widget.ui:59 src/ui/contact_list_widget.ui:350
+msgid "Create a conference"
+msgstr ""
-#: ui/ContactListWindow.vala:569
-#, c-format
-msgid "failed to send file %s to %s"
-msgstr "invio del file %s a %s fallito"
+#: src/ui/create_groupchat_widget.ui:147
+msgid "Name the conference (optional)"
+msgstr ""
-#: ui/ContactListWindow.vala:1077
-#, c-format
-msgid "groupchat #%i"
-msgstr "chat di gruppo #%i"
+#: src/ui/create_groupchat_widget.ui:242
+msgid "Select a conference type"
+msgstr ""
-#: ui/settings_window.ui:104
-msgid "indefinitely"
-msgstr "per sempre"
+#: src/ui/create_groupchat_widget.ui:288
+msgid "New conference"
+msgstr ""
-#: ui/ContactListWindow.vala:668
-msgid "lost"
-msgstr "persa"
+#: src/ui/create_groupchat_widget.ui:301 src/ui/create_groupchat_widget.ui:334
+msgid "Conference invites"
+msgstr ""
-#: core/GroupChat.vala:56
-msgid "no one connected"
-msgstr "nessuno connesso"
+#: src/ui/create_groupchat_widget.ui:390
+msgid "No new conference invites"
+msgstr ""
-#: ui/ContactListWindow.vala:663
-msgid "offline"
-msgstr "offline"
+#: src/ui/conversation_window.ui:134
+msgid "Start a video call"
+msgstr ""
-#: ui/ContactListWindow.vala:663
-msgid "online"
-msgstr "online"
+#: src/ui/friend_request_widget.ui:44
+msgid "_Public key:"
+msgstr ""
-#: ui/ContactListWindow.vala:798
-#, c-format
-msgid "received file send request friend: %i filenumber: %i filename: %s \n"
+#: src/ui/conference_info_widget.ui:56
+msgid "Leave Conference"
msgstr ""
-"ricevuta richiesta di trasferimento file contatto: %i numero file: %i nome "
-"file: %s \n"
-
-#: ui/ContactListWindow.vala:562
-#, c-format
-msgid "sending file %s to %s\n"
-msgstr "invio file %s a %s\n"
-
-#: ui/ContactListWindow.vala:1129
-#, c-format
-msgid "setting alias: %s\n"
-msgstr "impostazione alias: %s\n"
-
-#: core/ToxDns.vala:95
-#, c-format
-msgid "tox 1 ID found: %s\n"
-msgstr "Trovato Tox ID v1: %s\n"
-
-#: core/ToxDns.vala:100
-#, c-format
-msgid "tox 2 ID found: %s %s\n"
-msgstr "Trovato Tox ID v2: %s %s\n"
-
-#: ui/AboutDialog.vala:46
-msgid "translator-credits"
-msgstr "Ansa89"
+
+#: src/ui/conference_info_widget.ui:174 src/ui/friend_info_widget.ui:357
+msgid "Show notifications"
+msgstr ""
+
+#: src/ui/conference_info_widget.ui:212 src/ui/friend_info_widget.ui:395
+msgid "Notifications have been globally disabled"
+msgstr ""
+
+#: src/ui/conference_invite_entry.ui:43
+msgid "Invite from:"
+msgstr ""
+
+#: src/ui/conference_invite_entry.ui:87
+msgid "Accept invite"
+msgstr ""
+
+#: src/ui/conference_invite_entry.ui:111
+msgid "Reject invite"
+msgstr ""
+
+#: src/ui/add_contact_widget.ui:30
+msgid "No new friend requests"
+msgstr ""
+
+#: src/ui/add_contact_widget.ui:315
+msgid "Add a friend"
+msgstr ""
+
+#: src/ui/add_contact_widget.ui:328 src/ui/add_contact_widget.ui:361
+msgid "Friend requests"
+msgstr ""
+
+#: src/ui/user_info_widget.ui:158 src/ui/friend_info_widget.ui:155
+msgid "Status message:"
+msgstr ""
+
+#: src/ui/settings_widget.ui:1073
+msgid "Use UDP communication when available"
+msgstr ""
+
diff --git a/po/meson.build b/po/meson.build
new file mode 100644
index 0000000..e9b77d7
--- /dev/null
+++ b/po/meson.build
@@ -0,0 +1 @@
+i18n.gettext(meson.project_name(), preset: 'glib')
diff --git a/po/pl.po b/po/pl.po
new file mode 100644
index 0000000..43a5022
--- /dev/null
+++ b/po/pl.po
@@ -0,0 +1,748 @@
+# SOME DESCRIPTIVE TITLE.
+# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
+# This file is distributed under the same license as the PACKAGE package.
+# FIRST AUTHOR , YEAR.
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: Venom\n"
+"Report-Msgid-Bugs-To: \n"
+"POT-Creation-Date: 2014-10-10 04:00+0400\n"
+"PO-Revision-Date: 2014-08-14 20:22+0100\n"
+"Last-Translator: Zetok Zalbavar \n"
+"Language-Team: \n"
+"Language: pl\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"X-Generator: Poedit 1.5.5\n"
+"Plural-Forms: nplurals=3; plural=(n==1 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 "
+"|| n%100>=20) ? 1 : 2);\n"
+"X-Poedit-SourceCharset: UTF-8\n"
+"X-Poedit-Basepath: ../src/\n"
+
+#: Main.vala:50
+#, c-format
+msgid "'%s' not a positive number"
+msgstr ""
+
+#: Main.vala:68
+#, c-format
+msgid "error: %s\n"
+msgstr "błąd: %s\n"
+
+#: Main.vala:69
+#, c-format
+msgid "Run '%s --help' to see a full list of available command line options.\n"
+msgstr "Uruchom '%s --help' by zobaczyć pełną listę dostępnych opcji.\n"
+
+#: ui/user_info_window.ui:40
+msgid "ID:"
+msgstr "ID:"
+
+#: ui/user_info_window.ui:178
+msgid "Status message:"
+msgstr "Status:"
+
+#: ui/user_info_window.ui:192
+msgid "Name:"
+msgstr "Nazwa:"
+
+#: ui/user_info_window.ui:222
+msgid "Icon:"
+msgstr "Ikona:"
+
+#: ui/user_info_window.ui:254
+msgid "_Browse..."
+msgstr "_Przeglądaj..."
+
+#: ui/user_info_window.ui:282
+msgid "User"
+msgstr "Użytkownik"
+
+#: ui/UITools.vala:45 ui/UITools.vala:58
+#, c-format
+msgid "%llu bytes"
+msgstr ""
+
+#: ui/UITools.vala:46
+#, c-format
+msgid "%.2lf KiB"
+msgstr ""
+
+#: ui/UITools.vala:47
+#, c-format
+msgid "%.2lf MiB"
+msgstr ""
+
+#: ui/UITools.vala:48
+#, c-format
+msgid "%.2lf GiB"
+msgstr ""
+
+#: ui/UITools.vala:49
+#, c-format
+msgid "%.2lf TiB"
+msgstr ""
+
+#: ui/UITools.vala:59
+#, c-format
+msgid "%.2lf KB"
+msgstr ""
+
+#: ui/UITools.vala:60
+#, c-format
+msgid "%.2lf MB"
+msgstr ""
+
+#: ui/UITools.vala:61
+#, c-format
+msgid "%.2lf GB"
+msgstr ""
+
+#: ui/UITools.vala:62
+#, c-format
+msgid "%.2lf TB"
+msgstr ""
+
+#: ui/UITools.vala:65
+msgid "really big file"
+msgstr ""
+
+#: ui/UITools.vala:79
+msgid "_Unfriend"
+msgstr "_Usuń znajomego"
+
+#: ui/UITools.vala:89
+msgid "_File transfers"
+msgstr "Trans_fery plików"
+
+#: ui/UITools.vala:95
+msgid "_Audio chat"
+msgstr "Czat _audio"
+
+#: ui/UITools.vala:99
+msgid "_Video chat"
+msgstr "Czat _video"
+
+#: ui/UITools.vala:103
+msgid "_Automatically accept ..."
+msgstr "_Automatycznie akceptuj..."
+
+#: ui/UITools.vala:109
+msgid "_Invite to ..."
+msgstr "_Zaproś do ..."
+
+#: ui/UITools.vala:113
+msgid "_New groupchat"
+msgstr "_Nowy czat grupowy"
+
+#: ui/UITools.vala:125
+msgid "_Invite to new groupchat"
+msgstr "_Zaproś do nowego czatu grupowego"
+
+#: ui/UITools.vala:139
+msgid "_Leave groupchat"
+msgstr "_Opuść czat grupowy"
+
+#: ui/UITools.vala:148
+msgid "Export tox data file"
+msgstr "Eksportuj plik danych tox"
+
+#: ui/UITools.vala:150 ui/PinDialog.vala:48 ui/ContactListWindow.vala:680
+#: ui/ContactListWindow.vala:797 ui/ContactListWindow.vala:891
+#: ui/ContactListWindow.vala:1216 ui/ContactListWindow.vala:1253
+#: ui/AddContactDialog.vala:74 ui/FileTransferChatEntry.vala:157
+#: ui/UserInfoWindow.vala:82
+msgid "_Cancel"
+msgstr "_Anuluj"
+
+#: ui/UITools.vala:150 ui/FileTransferChatEntry.vala:158
+msgid "_Save"
+msgstr "Zapi_sz"
+
+#: ui/UITools.vala:166
+msgid "Exporting data file failed"
+msgstr "Eksport pliku danych nieudany"
+
+#: ui/UITools.vala:166
+msgid "Could not export data file: "
+msgstr "Nie udało się wyeksportować pliku danych: "
+
+#: ui/UITools.vala:172
+msgid "Importing data files is currently not supported"
+msgstr "Importowanie pliku danych nie jest obecnie wspierane"
+
+#: ui/settings_window.ui:14
+msgid "KiB/MiB"
+msgstr "KiB/MiB"
+
+#: ui/settings_window.ui:18
+msgid "KB/MB"
+msgstr "KB/MB"
+
+#: ui/settings_window.ui:30
+msgid "Settings"
+msgstr "Ustawienia"
+
+#: ui/settings_window.ui:79
+msgid "Keep history"
+msgstr "Trzymaj historię przez"
+
+#: ui/settings_window.ui:105
+msgid "indefinitely"
+msgstr "nieskończoność"
+
+#: ui/settings_window.ui:127
+msgid "delete after"
+msgstr "usuń po"
+
+#: ui/settings_window.ui:160
+msgid "days"
+msgstr "dniach"
+
+#: ui/settings_window.ui:186
+msgid "Show _others when I am typing"
+msgstr "P_okaż innym gdy piszę"
+
+#: ui/settings_window.ui:202
+msgid "Show me when others are typing"
+msgstr "Pokaż gdy inni piszą"
+
+#: ui/settings_window.ui:221
+msgid "Privacy"
+msgstr "Prywatność"
+
+#: ui/settings_window.ui:236
+msgid "Flash window when a new message arrives"
+msgstr "Migaj oknem gdy przychodzi nowa wiadomość"
+
+#: ui/settings_window.ui:251
+msgid "Play notification sounds"
+msgstr ""
+
+#: ui/settings_window.ui:266
+msgid "Show notification when a new message arrives"
+msgstr "Pokaż powiadomienie gdy przychodzi nowa wiadomość"
+
+#: ui/settings_window.ui:288
+msgid "Notifications"
+msgstr ""
+
+#: ui/settings_window.ui:323 ui/settings_window.ui:398
+msgid "Recording device"
+msgstr ""
+
+#: ui/settings_window.ui:337 ui/settings_window.ui:412
+msgid "System default"
+msgstr ""
+
+#: ui/settings_window.ui:348 ui/settings_window.ui:423
+msgid "Preview"
+msgstr ""
+
+#: ui/settings_window.ui:367
+#, fuzzy
+msgid "Audio"
+msgstr "Czat _audio"
+
+#: ui/settings_window.ui:442
+#, fuzzy
+msgid "Video"
+msgstr "Czat _video"
+
+#: ui/settings_window.ui:461
+msgid "Audio / Video"
+msgstr ""
+
+#: ui/settings_window.ui:477
+msgid "Minimize to system tray"
+msgstr "Minimalizuj do systemowego traya"
+
+#: ui/settings_window.ui:499
+msgid "Default Tox DNS ID suffix:"
+msgstr "Domyślny sufix Tox DNS ID:"
+
+#: ui/settings_window.ui:535
+msgid "Show filesize in"
+msgstr "Pokaż rozmiar pliku w"
+
+#: ui/settings_window.ui:578
+msgid "Miscellaneous"
+msgstr "Różne"
+
+#. dennis-ignore: W303
+#: ui/AboutDialog.vala:46
+msgid "translator-credits"
+msgstr "Zetok Zalbavar "
+
+#: ui/PinDialog.vala:37
+#, c-format
+msgid ""
+"Please insert PIN for \n"
+"%s"
+msgstr ""
+"Proszę wprowadzić PIN dla \n"
+"%s"
+
+#: ui/PinDialog.vala:48
+msgid "_Ok"
+msgstr ""
+
+#: ui/PinDialog.vala:49
+msgid "Please insert PIN..."
+msgstr "Proszę wprowadzić PIN..."
+
+#: ui/MessageTextView.vala:27
+msgid "Type your message here..."
+msgstr "Wpisz swoją wiadomość tutaj..."
+
+#: ui/ContactListWindow.vala:131
+#, c-format
+msgid "Could not read theme from \"%s\""
+msgstr "Nie udało się odczytać motywu z \"%s\""
+
+#: ui/ContactListWindow.vala:210 core/ToxSession.vala:31
+#: core/GroupChatContact.vala:32
+msgid "Online"
+msgstr "Online"
+
+#: ui/ContactListWindow.vala:212
+msgid "All"
+msgstr "Wszyscy"
+
+#: ui/ContactListWindow.vala:679
+#, c-format
+msgid ""
+"New friend request from '%s'.\n"
+"Do you want to accept?"
+msgstr ""
+"Nowe zapytanie o dodanie do znajomych od '%s'.\n"
+"Czy chcesz zaakceptować?"
+
+#: ui/ContactListWindow.vala:680 ui/ContactListWindow.vala:797
+#: ui/ContactListWindow.vala:891
+msgid "_Accept"
+msgstr "_Akceptuj"
+
+#: ui/ContactListWindow.vala:745
+msgid "Connected to the network"
+msgstr "Połączono z siecią"
+
+#: ui/ContactListWindow.vala:751
+msgid "Disconnected from the network"
+msgstr "Rozłączono z siecią"
+
+#: ui/ContactListWindow.vala:795
+#, c-format
+msgid "'%s' has invited you to a groupchat, do you want to accept?"
+msgstr "'%s' zaprosił cię do rozmowy grupowej, czy chcesz zaakceptować?"
+
+#: ui/ContactListWindow.vala:890
+#, fuzzy, c-format
+msgid "'%s' is calling (%s) ..."
+msgstr "%s pisze..."
+
+#: ui/ContactListWindow.vala:890
+#, fuzzy
+msgid "Video call"
+msgstr "Czat _video"
+
+#: ui/ContactListWindow.vala:890
+#, fuzzy
+msgid "Audio only"
+msgstr "Czat _audio"
+
+#: ui/ContactListWindow.vala:1215 ui/ContactListWindow.vala:1252
+#, c-format
+msgid "Are you sure you want to remove '%s' from your contact list?"
+msgstr "Czy na pewno chcesz usunąć '%s' z listy kontaktów?"
+
+#: ui/ContactListWindow.vala:1216 ui/ContactListWindow.vala:1253
+msgid "_Delete"
+msgstr ""
+
+#: ui/ContactListWindow.vala:1283
+msgid "Resolving ID failed"
+msgstr "Rozwiązywanie ID nie powiodło się"
+
+#: ui/ContactListWindow.vala:1283
+msgid "Could not resolve ID from DNS record\n"
+msgstr "Nie udało się rozwiązać ID z rekordu DNS\n"
+
+#: ui/ContactListWindow.vala:1293 ui/ContactListWindow.vala:1304
+msgid "Adding Friend failed"
+msgstr "Dodawanie znajomego nieudane"
+
+#: ui/ContactListWindow.vala:1293
+msgid "Could not add friend: Invalid ID\n"
+msgstr "Nie udało się dodać znajomego: niepoprawny ID\n"
+
+#: ui/ContactListWindow.vala:1304
+#, c-format
+msgid "Could not add friend: %s.\n"
+msgstr "Nie udało się dodać znajomego: %s.\n"
+
+#: ui/add_contact_dialog.ui:6
+msgid "Please let me add you to my contact list."
+msgstr "Proszę dodaj mnie do listy znajomych."
+
+#: ui/add_contact_dialog.ui:40
+msgid "Enter a Tox ID here or a Tox URI"
+msgstr "Wpisz tu Tox ID lub Tox URI"
+
+#: ui/add_contact_dialog.ui:54
+msgid "_Nickname (optional):"
+msgstr "_Nick (opcjonalny):"
+
+#: ui/add_contact_dialog.ui:67
+msgid "Set a custom nickname for the friend you are about to add"
+msgstr "Ustaw własny nick dla dodawanego znajomego"
+
+#: ui/add_contact_dialog.ui:94
+msgid "_Message (optional):"
+msgstr "Wiado_mość (opcjonalna):"
+
+#: ui/add_contact_dialog.ui:113
+msgid "Send a custom message to be displayed to the friend you are adding"
+msgstr ""
+"Wyślij własną wiadomość, która będzie wyświetlona dla znajomego którego "
+"dodajesz"
+
+#: ui/AddContactDialog.vala:74
+msgid "_Add"
+msgstr ""
+
+#: ui/AddContactDialog.vala:76 ui/contact_list.ui:427
+msgid "Add contact"
+msgstr "Dodaj kontakt"
+
+#: ui/AddContactDialog.vala:90
+msgid "No ID given"
+msgstr "Nie podano ID"
+
+#: ui/AddContactDialog.vala:96
+msgid "ID contains invalid characters"
+msgstr "ID zawiera nieprawidłowe znaki"
+
+#: ui/AddContactDialog.vala:100
+msgid "Valid ID size"
+msgstr "Poprawny rozmiar ID"
+
+#: ui/contact_list.ui:50
+msgid "_Edit user"
+msgstr "_Edytuj użytkownika"
+
+#: ui/contact_list.ui:61
+msgid "_Copy ID to clipboard"
+msgstr "Kopiuj ID do s_chowka"
+
+#: ui/contact_list.ui:72
+msgid "Change _Status"
+msgstr "Zmień _Status"
+
+#: ui/contact_list.ui:85
+msgid "_Online"
+msgstr "_Online"
+
+#: ui/contact_list.ui:96
+msgid "_Away"
+msgstr "_Nieobecny"
+
+#: ui/contact_list.ui:107
+msgid "_Busy"
+msgstr "_Zajęty"
+
+#: ui/contact_list.ui:118
+msgid "O_ffline"
+msgstr "O_ffline"
+
+#: ui/contact_list.ui:141
+msgid "E_xport data file"
+msgstr "_Eksportuj plik danych"
+
+#: ui/contact_list.ui:149
+msgid "_Import data file"
+msgstr "_Importuj plik danych"
+
+#: ui/contact_list.ui:306
+msgid "connecting..."
+msgstr "łączenie..."
+
+#: ui/contact_list.ui:444
+msgid "Create groupchat"
+msgstr "Utwórz czat grupowy"
+
+#: ui/contact_list.ui:477
+msgid "Open preferences"
+msgstr "Otwórz ustawienia"
+
+#: ui/ConversationWidget.vala:68
+#, c-format
+msgid "%s is typing..."
+msgstr "%s pisze..."
+
+#: ui/ConversationWidget.vala:364
+msgid "Select a file to send"
+msgstr "Wybierz plik do wysłania"
+
+#: ui/ConversationWidget.vala:367
+msgid "Select"
+msgstr "Wybierz"
+
+#: ui/FileTransferChatEntry.vala:85
+msgid "File received"
+msgstr "Plik odebrany"
+
+#: ui/FileTransferChatEntry.vala:87
+msgid "File sent"
+msgstr "Plik wysłany"
+
+#: ui/FileTransferChatEntry.vala:94
+msgid "File was rejected"
+msgstr "Plik został odrzucony"
+
+#: ui/FileTransferChatEntry.vala:104
+msgid "Paused"
+msgstr "Wstrzymany"
+
+#: ui/FileTransferChatEntry.vala:107
+msgid "Sending failed"
+msgstr "Wysyłanie nie powiodło się"
+
+#: ui/FileTransferChatEntry.vala:113
+msgid "Receiving failed"
+msgstr "Odbieranie nie powiodło się"
+
+#: ui/FileTransferChatEntry.vala:119
+msgid "Canceled"
+msgstr "Anulowane"
+
+#: ui/FileTransferChatEntry.vala:125 ui/FileTransferChatEntry.vala:129
+msgid "Disconnected"
+msgstr "Rozłączony"
+
+#: ui/FileTransferChatEntry.vala:155
+msgid "Save file"
+msgstr "Zapisz plik"
+
+#: ui/conversation_window.ui:156
+msgid "Call contact"
+msgstr "Zadzwoń do kontaktu"
+
+#: ui/conversation_window.ui:175
+msgid "Call contact with video"
+msgstr "Zadzwoń do kontaku z wideo"
+
+#: ui/conversation_window.ui:291
+msgid "Insert Smiley"
+msgstr "Wstaw uśmiech"
+
+#: ui/conversation_window.ui:309
+msgid "Send file"
+msgstr "Wyślij plik"
+
+#: ui/conversation_window.ui:342
+msgid "Send message"
+msgstr "Wyślij wiadomość"
+
+#: ui/Client.vala:49
+#, fuzzy
+msgid "P_references"
+msgstr "Otwórz ustawienia"
+
+#: ui/Client.vala:53
+msgid "_Help"
+msgstr ""
+
+#: ui/Client.vala:57
+msgid "_About"
+msgstr ""
+
+#: ui/Client.vala:60 ui/Client.vala:86
+msgid "_Quit"
+msgstr "_Wyjdź"
+
+#: ui/Client.vala:83
+msgid "_Show/Hide Venom"
+msgstr "_Pokaż/Ukryj Venom"
+
+#: ui/Client.vala:182
+msgid "There is currently no help available"
+msgstr "Obecnie nie ma dostępnej pomocy"
+
+#: ui/UserInfoWindow.vala:83
+msgid "_Apply"
+msgstr ""
+
+#: ui/UserInfoWindow.vala:86
+msgid "Edit user information"
+msgstr "Edytuj informacje użytkownika"
+
+#: core/GroupChat.vala:45
+#, c-format
+msgid "Groupchat #%i"
+msgstr "Czat grupowy #%i"
+
+#: core/GroupChat.vala:52
+#, c-format
+msgid "%i people connected"
+msgstr "%i osób połączonych"
+
+#: core/GroupChat.vala:54
+#, c-format
+msgid "%i person connected"
+msgstr "%i osoba połączona"
+
+#: core/GroupChat.vala:56
+msgid "no one connected"
+msgstr "nikt nie połączył się"
+
+#: core/ToxSession.vala:33
+msgid "Away"
+msgstr "Nieobecny"
+
+#: core/ToxSession.vala:35
+msgid "Busy"
+msgstr "Zajęty"
+
+#: core/ToxSession.vala:37 core/Contact.vala:129 core/Contact.vala:139
+msgid "Offline"
+msgstr "Offline"
+
+#: core/ToxSession.vala:873
+#, c-format
+msgid "File \"%d\" does not exist."
+msgstr "Plik \"%d\" nie istnieje."
+
+#: core/ToxSession.vala:880
+msgid "Error while reading from stream."
+msgstr ""
+
+#: core/ToxSession.vala:886
+msgid "Error while loading messenger data."
+msgstr ""
+
+#: core/Tools.vala:138
+msgid "Message too long"
+msgstr "Wiadomość zbyt długa"
+
+#: core/Tools.vala:140
+msgid "No message included"
+msgstr "Nie załączono wiadomości"
+
+#: core/Tools.vala:142
+msgid "Can't send to own key"
+msgstr "Nie można wysłać do własnego klucza"
+
+#: core/Tools.vala:144
+msgid "Friend request already sent"
+msgstr "Zapytanie już zostało wysłane"
+
+#: core/Tools.vala:146
+msgid "Unknown error"
+msgstr "Nieznany błąd"
+
+#: core/Tools.vala:148
+msgid "Bad checksum"
+msgstr "Zła suma kontrolna"
+
+#: core/Tools.vala:150
+msgid "Set new nospam"
+msgstr "Ustaw nowy nospam"
+
+#: core/Tools.vala:152
+msgid "Out of memory"
+msgstr ""
+
+#: core/Tools.vala:154
+msgid "Friend request successfully sent"
+msgstr "Zapytanie zostało pomyślnie wysłane"
+
+#: core/ContactStorage.vala:103
+#, c-format
+msgid "Error creating contacts table: %s\n"
+msgstr ""
+
+#: core/ContactStorage.vala:108
+#, c-format
+msgid "Error creating contacts insert statement: %d: %s\n"
+msgstr ""
+
+#: core/ContactStorage.vala:113
+#, c-format
+msgid "Error creating contacts select statement: %d: %s\n"
+msgstr ""
+
+#: core/Message.vala:92
+#, c-format
+msgid "%s says:"
+msgstr "%s pisze:"
+
+#: core/Message.vala:164 core/Message.vala:209
+msgid ""
+msgstr ""
+
+#: core/Message.vala:171
+#, c-format
+msgid "%s in %s says:"
+msgstr "%s w %s napisał:"
+
+#: core/Message.vala:216
+#, c-format
+msgid "%s in %s:"
+msgstr "%s w %s:"
+
+#: core/DhtNodeStorage.vala:172
+#, c-format
+msgid "Error creating dht nodes table: %s\n"
+msgstr ""
+
+#: core/DhtNodeStorage.vala:177
+#, c-format
+msgid "Error creating dht nodes insert statement: %d: %s\n"
+msgstr ""
+
+#: core/DhtNodeStorage.vala:182
+#, c-format
+msgid "Error creating dht nodes select statement: %d: %s\n"
+msgstr ""
+
+#: core/ResourceFactory.vala:76
+msgid "Tox User"
+msgstr "Użytkownik Tox"
+
+#: core/ResourceFactory.vala:77
+#, c-format
+msgid "Toxing on Venom v.%s"
+msgstr "Toxing na Venom v.%s"
+
+#: core/SqliteTools.vala:37 core/SqliteTools.vala:47 core/SqliteTools.vala:57
+#, c-format
+msgid "Index for %s not found."
+msgstr ""
+
+#: core/SqliteTools.vala:40
+#, c-format
+msgid "Could not bind int to %s."
+msgstr ""
+
+#: core/SqliteTools.vala:50
+#, c-format
+msgid "Could not bind int64 to %s."
+msgstr ""
+
+#: core/SqliteTools.vala:60
+#, c-format
+msgid "Could not bind text to %s"
+msgstr ""
+
+#: core/SqliteTools.vala:75
+#, c-format
+msgid "Can't open database: %d: %s\n"
+msgstr "Nie można otworzyć bazy danych: %d: %s\n"
+
+#: core/Contact.vala:148
+#, c-format
+msgid "Last seen: %s"
+msgstr "Ostatnio widziany: %s"
diff --git a/po/pr.po b/po/pr.po
new file mode 100644
index 0000000..d958505
--- /dev/null
+++ b/po/pr.po
@@ -0,0 +1,635 @@
+msgid ""
+msgstr ""
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"X-Generator: POEditor.com\n"
+"Project-Id-Version: Venom\n"
+"Language: pt\n"
+"Plural-Forms: nplurals=2; plural=(n != 1);\n"
+
+#: src/core/Application.vala:32
+msgid "Set level of messages to log"
+msgstr "Defina o nível de mensagens para logar"
+
+#: src/core/Application.vala:32
+msgid ""
+msgstr ""
+
+#: src/core/Application.vala:33
+msgid "Display version number"
+msgstr "Exibir o número da versão"
+
+#: src/core/NotificationListener.vala:55
+msgid "New message from %s"
+msgstr "Nova mensagem de %s"
+
+#: src/core/R.vala:70
+msgid "Tox User"
+msgstr "Usuário Tox"
+
+#: src/tox/Conference.vala:47
+msgid "%u Peers online"
+msgstr "%u Peers online"
+
+#: src/view/AboutDialog.vala:53
+msgid "Packagers"
+msgstr "Embaladores"
+
+#: src/view/AboutDialog.vala:58
+msgid "translator-credits"
+msgstr ""
+
+#: src/view/AboutDialog.vala:61
+msgid "Visit us on Github"
+msgstr "Visite-nos em Github"
+
+#: src/ui/add_contact_widget.ui:43
+msgid "Please let me add you to my contact list. 😁"
+msgstr "Por favor, deixe-me adicioná-lo à minha lista de contatos. 😁"
+
+#: src/ui/add_contact_widget.ui:99
+msgid "Send a friend request"
+msgstr "Envie uma solicitação de amizade"
+
+#: src/ui/add_contact_widget.ui:133
+msgid "_ID:"
+msgstr ""
+
+#: src/ui/add_contact_widget.ui:150
+msgid "Enter a Tox ID or URI here"
+msgstr "Digite uma ID de Tox ou URI aqui"
+
+#: src/ui/create_groupchat_widget.ui:113 src/ui/add_contact_widget.ui:154
+msgid "paste from clipboard"
+msgstr "colar da área de transferência"
+
+#: src/ui/add_contact_widget.ui:188
+msgid "Enter your friends Tox ID"
+msgstr ""
+
+#: src/ui/friend_request_widget.ui:78 src/ui/add_contact_widget.ui:220
+msgid "_Message:"
+msgstr "_Mensagem:"
+
+#: src/ui/add_contact_widget.ui:246
+msgid "Send a custom message to be displayed to the friend you are adding"
+msgstr "Envie uma mensagem personalizada a ser exibida para o amigo que você está adicionando"
+
+#: src/ui/add_contact_widget.ui:268
+msgid "Send your friend a short message"
+msgstr ""
+
+#: src/ui/add_contact_widget.ui:298
+msgid "Send"
+msgstr "Enviar"
+
+#: src/ui/app_menu.ui:7
+msgid "_Preferences"
+msgstr "_Preferências"
+
+#: src/ui/app_menu.ui:13
+msgid "About"
+msgstr "Sobre"
+
+#: src/ui/app_menu.ui:17
+msgid "_Quit"
+msgstr "_Sair"
+
+#: src/ui/create_groupchat_widget.ui:112 src/ui/conference_info_widget.ui:39
+msgid "Conference"
+msgstr "Conferência"
+
+#: src/ui/conference_info_widget.ui:105
+msgid "Title:"
+msgstr "Título:"
+
+#: src/ui/conference_info_widget.ui:243 src/ui/user_info_widget.ui:449
+#: src/ui/friend_info_widget.ui:666
+msgid "Apply"
+msgstr "Aplique"
+
+#: src/ui/conference_info_widget.ui:261
+msgid "Peers"
+msgstr "Pares"
+
+#: src/ui/conference_window.ui:209 src/ui/conversation_window.ui:268
+#: src/ui/user_info_widget.ui:177 src/ui/user_info_widget.ui:178
+msgid "Insert Emoji"
+msgstr "Inserir Emoji"
+
+#: src/ui/contact_list_widget.ui:216
+msgid "Filter contacts by status"
+msgstr "Filtrar contatos por status"
+
+#: src/ui/contact_list_widget.ui:222
+msgid "All"
+msgstr "Todos"
+
+#: src/ui/contact_list_widget.ui:329
+msgid "Add a contact"
+msgstr "Adicionar um contato"
+
+#: src/ui/contact_list_widget.ui:371
+msgid "View file transfers"
+msgstr "Ver transferências de arquivos"
+
+#: src/ui/contact_list_widget.ui:392
+msgid "Open preferences"
+msgstr "Preferências abertas"
+
+#: src/ui/conversation_window.ui:109
+msgid "Start a call"
+msgstr "Iniciar uma chamada"
+
+#: src/ui/conversation_window.ui:290
+msgid "Insert attachment"
+msgstr "Inserir anexo"
+
+#: src/ui/create_groupchat_widget.ui:93
+msgid "_Title:"
+msgstr "_Título:"
+
+#: src/ui/create_groupchat_widget.ui:179
+msgid "T_ype:"
+msgstr "Tipo:"
+
+#: src/ui/create_groupchat_widget.ui:271
+msgid "Create"
+msgstr "Crio"
+
+#: src/ui/file_transfer_widget.ui:35
+msgid "File transfers"
+msgstr "Transferências de arquivos"
+
+#: src/ui/friend_info_widget.ui:45
+msgid "Friend profile"
+msgstr "Perfil do amigo"
+
+#: src/ui/friend_info_widget.ui:62
+msgid "Remove from your friends list"
+msgstr "Remover da sua lista de amigos"
+
+#: src/ui/user_info_widget.ui:113 src/ui/friend_info_widget.ui:111
+msgid "Username:"
+msgstr "Nome de usuário:"
+
+#: src/ui/user_info_widget.ui:206 src/ui/friend_info_widget.ui:200
+msgid "Image:"
+msgstr "Imagem:"
+
+#: src/ui/friend_info_widget.ui:245
+msgid "Last seen:"
+msgstr "Visto pela última vez:"
+
+#: src/ui/friend_info_widget.ui:290
+msgid "Alias:"
+msgstr "Alias:"
+
+#: src/ui/friend_info_widget.ui:321
+msgid "Set a custom alias to quickly find your friends"
+msgstr "Defina um alias personalizado para encontrar rapidamente seus amigos"
+
+#: src/ui/user_info_widget.ui:291 src/ui/friend_info_widget.ui:579
+msgid "Tox"
+msgstr "Tox"
+
+#: src/ui/user_info_widget.ui:330 src/ui/friend_info_widget.ui:612
+msgid "ID:"
+msgstr ""
+
+#: src/ui/message_widget.ui:91
+msgid "Message sent ✓"
+msgstr "Mensagem enviada ✓"
+
+#: src/ui/message_widget.ui:107
+msgid "Message received ✓"
+msgstr "Mensagem recebida ✓"
+
+#: src/ui/peer_entry.ui:55
+msgid "This peer is also in your friends list"
+msgstr "Este ponto também está na lista de amigos"
+
+#: src/ui/settings_widget.ui:38
+msgid "KiB/MiB"
+msgstr "KiB / MiB"
+
+#: src/ui/settings_widget.ui:42
+msgid "KB/MB"
+msgstr "KB / MB"
+
+#: src/ui/settings_widget.ui:98
+msgid "General"
+msgstr "Geral"
+
+#: src/ui/settings_widget.ui:268
+msgid "Appearance"
+msgstr "Aparência"
+
+#: src/ui/settings_widget.ui:313
+msgid "Dark Theme"
+msgstr "Tema escuro"
+
+#: src/ui/settings_widget.ui:523
+msgid "Minimize to tray"
+msgstr "Minimizar para a bandeja"
+
+#: src/ui/settings_widget.ui:619
+msgid "Privacy"
+msgstr "Privacidade"
+
+#: src/ui/settings_widget.ui:663
+msgid "Send typing notifications"
+msgstr "Enviar notificações de digitação"
+
+#: src/ui/settings_widget.ui:676
+msgid "Show others when I am typing"
+msgstr "Mostra os outros quando estou digitando"
+
+#: src/ui/settings_widget.ui:759
+msgid "History"
+msgstr "História"
+
+#: src/ui/settings_widget.ui:893
+msgid "days"
+msgstr "dias"
+
+#: src/ui/settings_widget.ui:923
+msgid "Delete all previous conversations"
+msgstr "Apague todas as conversas anteriores"
+
+#: src/ui/settings_widget.ui:1340
+msgid "Update bootstrap nodes"
+msgstr "Atualize os nós do bootstrap"
+
+#: src/ui/user_info_widget.ui:79
+msgid "User profile"
+msgstr "Perfil de usuário"
+
+#: src/ui/user_info_widget.ui:372
+msgid "Copy to clipboard"
+msgstr "Copiar para área de transferência"
+
+#: src/ui/welcome_widget.ui:40
+msgid "A new kind of instant messaging"
+msgstr "Um novo tipo de mensagens instantâneas"
+
+#: src/ui/welcome_widget.ui:56
+msgid "Chat with your friends and family without anyone else listening in."
+msgstr "Conversar com seus amigos e familiares sem que ninguém mais ouça."
+
+#: src/ui/welcome_widget.ui:109
+msgid "Learn more"
+msgstr "Saber mais"
+
+#: src/core/Message.vala:76 src/viewmodel/MessageViewModel.vala:87
+#: src/tox/ConferenceMessage.vala:56
+msgid "me"
+msgstr "mim"
+
+#: src/ui/user_info_widget.ui:244
+msgid "Choose an avatar"
+msgstr "Escolha um avatar"
+
+#: src/ui/friend_request_widget.ui:146
+msgid "Reject request"
+msgstr "Rejeitar pedido"
+
+#: src/ui/friend_request_widget.ui:170
+msgid "Accept request"
+msgstr "Aceitar pedido"
+
+#: src/ui/application_window.ui:55
+msgid "venom"
+msgstr ""
+
+#: src/core/NotificationListener.vala:76
+msgid "New file from %s"
+msgstr ""
+
+#: src/viewmodel/ContactListEntryViewModel.vala:58
+msgid "New Message!"
+msgstr ""
+
+#: src/viewmodel/ContactListEntryViewModel.vala:64
+msgid "Offline"
+msgstr ""
+
+#: src/viewmodel/ContactListEntryViewModel.vala:72
+#: src/ui/user_status_menu.ui:11
+msgid "Away"
+msgstr ""
+
+#: src/viewmodel/ContactListEntryViewModel.vala:74
+#: src/ui/user_status_menu.ui:17
+msgid "Busy"
+msgstr ""
+
+#: src/viewmodel/ContactListEntryViewModel.vala:76 src/ui/user_status_menu.ui:5
+msgid "Online"
+msgstr ""
+
+#: src/viewmodel/MessageViewModel.vala:65
+msgid "Today at %s"
+msgstr ""
+
+#: src/viewmodel/MessageViewModel.vala:69
+msgid "Yesterday at %s"
+msgstr ""
+
+#: src/tox/Conference.vala:43
+msgid "Unnamed conference %u"
+msgstr ""
+
+#: src/tox/ToxSession.vala:645
+msgid "Address must consist of 76 hexadecimal characters"
+msgstr ""
+
+#: src/view/ConversationWindow.vala:102
+msgid "%s is typing..."
+msgstr ""
+
+#: src/view/ConversationWindow.vala:168 src/view/FileTransferEntry.vala:76
+msgid "_Cancel"
+msgstr ""
+
+#: src/view/ConversationWindow.vala:169
+msgid "_Open"
+msgstr ""
+
+#: src/view/FileTransferEntry.vala:77
+msgid "_Save"
+msgstr ""
+
+#: src/ui/file_transfer_widget.ui:117
+msgid "No file transfers yet …"
+msgstr ""
+
+#: src/ui/file_transfer_entry.ui:34
+msgid "Remove transfer"
+msgstr ""
+
+#: src/ui/file_transfer_entry.ui:102
+msgid "Open file"
+msgstr ""
+
+#: src/ui/file_transfer_entry.ui:126
+msgid "Start transfer"
+msgstr ""
+
+#: src/ui/file_transfer_entry.ui:147
+msgid "Pause transfer"
+msgstr ""
+
+#: src/ui/file_transfer_entry.ui:168
+msgid "Stop transfer"
+msgstr ""
+
+#: src/ui/create_groupchat_widget.ui:199
+msgid "Text"
+msgstr ""
+
+#: src/ui/create_groupchat_widget.ui:214
+msgid "Speech"
+msgstr ""
+
+#: src/ui/peer_entry.ui:68
+msgid "That's you"
+msgstr ""
+
+#: src/ui/welcome_widget.ui:156
+msgid "Get involved"
+msgstr ""
+
+#: src/ui/settings_widget.ui:181
+msgid "Proxy"
+msgstr ""
+
+#: src/ui/settings_widget.ui:326
+msgid "Use a dark variant of the theme"
+msgstr ""
+
+#: src/ui/settings_widget.ui:383
+msgid "Animations"
+msgstr ""
+
+#: src/ui/settings_widget.ui:396
+msgid "Enable animated transitions"
+msgstr ""
+
+#: src/ui/settings_widget.ui:453
+msgid "Notifications"
+msgstr ""
+
+#: src/ui/settings_widget.ui:466
+msgid "Show notifications for unread messages"
+msgstr ""
+
+#: src/ui/settings_widget.ui:536
+msgid "Minimize app to system tray on close"
+msgstr ""
+
+#: src/ui/settings_widget.ui:823
+msgid "Keep forever"
+msgstr ""
+
+#: src/ui/settings_widget.ui:860
+msgid "Remove older than"
+msgstr ""
+
+#: src/ui/settings_widget.ui:1017
+msgid "Connection"
+msgstr ""
+
+#: src/ui/settings_widget.ui:1060
+msgid "UDP"
+msgstr ""
+
+#: src/ui/settings_widget.ui:1130
+msgid "IPv6"
+msgstr ""
+
+#: src/ui/settings_widget.ui:1143
+msgid "Allow both IPv4 and IPv6 communication"
+msgstr ""
+
+#: src/ui/settings_widget.ui:1200
+msgid "Local discovery"
+msgstr ""
+
+#: src/ui/settings_widget.ui:1213
+msgid "Look for peers on the local network"
+msgstr ""
+
+#: src/ui/settings_widget.ui:1270
+msgid "Hole punching"
+msgstr ""
+
+#: src/ui/settings_widget.ui:1283
+msgid "Enable UDP hole punching"
+msgstr ""
+
+#: src/ui/settings_widget.ui:1376
+msgid "Bootstrap nodes"
+msgstr ""
+
+#: src/ui/settings_widget.ui:1511
+msgid "Proxy"
+msgstr ""
+
+#: src/ui/settings_widget.ui:1578
+msgid "System settings"
+msgstr ""
+
+#: src/ui/settings_widget.ui:1591
+msgid "Use your systems proxy settings"
+msgstr ""
+
+#: src/ui/settings_widget.ui:1645
+msgid "Manual settings"
+msgstr ""
+
+#: src/ui/settings_widget.ui:1658
+msgid "Use custom proxy settings"
+msgstr ""
+
+#: src/ui/settings_widget.ui:1699
+msgid "Host"
+msgstr ""
+
+#: src/ui/settings_widget.ui:1739
+msgid "Set a SOCKS5 proxy to connect to"
+msgstr ""
+
+#: src/ui/friend_info_widget.ui:309
+msgid "Reset alias"
+msgstr ""
+
+#: src/ui/friend_info_widget.ui:428
+msgid "Auto accept conference invites"
+msgstr ""
+
+#: src/ui/friend_info_widget.ui:474
+msgid "Auto accept file transfers"
+msgstr ""
+
+#: src/ui/friend_info_widget.ui:517
+msgid "Save files to"
+msgstr ""
+
+#: src/viewmodel/ContactListViewModel.vala:102
+msgid "New conference…"
+msgstr ""
+
+#: src/viewmodel/ContactListViewModel.vala:115
+msgid "Invite to conference"
+msgstr ""
+
+#: src/viewmodel/ContactListViewModel.vala:118
+msgid "Show details"
+msgstr ""
+
+#: src/viewmodel/ContactListViewModel.vala:140
+msgid "%u new friend request"
+msgid_plural "%u new friend requests"
+msgstr[0] ""
+msgstr[1] ""
+
+#: src/viewmodel/ContactListViewModel.vala:148
+msgid "%u new conference invite"
+msgid_plural "%u new conference invites"
+msgstr[0] ""
+msgstr[1] ""
+
+#: src/viewmodel/MessageViewModel.vala:51
+msgid "Just now"
+msgstr ""
+
+#: src/viewmodel/MessageViewModel.vala:56
+msgid "%u minute ago"
+msgid_plural "%u minutes ago"
+msgstr[0] ""
+msgstr[1] ""
+
+#: src/viewmodel/MessageViewModel.vala:61
+msgid "%u hour ago"
+msgid_plural "%u hours ago"
+msgstr[0] ""
+msgstr[1] ""
+
+#: src/ui/create_groupchat_widget.ui:59 src/ui/contact_list_widget.ui:350
+msgid "Create a conference"
+msgstr ""
+
+#: src/ui/create_groupchat_widget.ui:147
+msgid "Name the conference (optional)"
+msgstr ""
+
+#: src/ui/create_groupchat_widget.ui:242
+msgid "Select a conference type"
+msgstr ""
+
+#: src/ui/create_groupchat_widget.ui:288
+msgid "New conference"
+msgstr ""
+
+#: src/ui/create_groupchat_widget.ui:301 src/ui/create_groupchat_widget.ui:334
+msgid "Conference invites"
+msgstr ""
+
+#: src/ui/create_groupchat_widget.ui:390
+msgid "No new conference invites"
+msgstr ""
+
+#: src/ui/conversation_window.ui:134
+msgid "Start a video call"
+msgstr ""
+
+#: src/ui/friend_request_widget.ui:44
+msgid "_Public key:"
+msgstr ""
+
+#: src/ui/conference_info_widget.ui:56
+msgid "Leave Conference"
+msgstr ""
+
+#: src/ui/conference_info_widget.ui:174 src/ui/friend_info_widget.ui:357
+msgid "Show notifications"
+msgstr ""
+
+#: src/ui/conference_info_widget.ui:212 src/ui/friend_info_widget.ui:395
+msgid "Notifications have been globally disabled"
+msgstr ""
+
+#: src/ui/conference_invite_entry.ui:43
+msgid "Invite from:"
+msgstr ""
+
+#: src/ui/conference_invite_entry.ui:87
+msgid "Accept invite"
+msgstr ""
+
+#: src/ui/conference_invite_entry.ui:111
+msgid "Reject invite"
+msgstr ""
+
+#: src/ui/add_contact_widget.ui:30
+msgid "No new friend requests"
+msgstr ""
+
+#: src/ui/add_contact_widget.ui:315
+msgid "Add a friend"
+msgstr ""
+
+#: src/ui/add_contact_widget.ui:328 src/ui/add_contact_widget.ui:361
+msgid "Friend requests"
+msgstr ""
+
+#: src/ui/user_info_widget.ui:158 src/ui/friend_info_widget.ui:155
+msgid "Status message:"
+msgstr ""
+
+#: src/ui/settings_widget.ui:1073
+msgid "Use UDP communication when available"
+msgstr ""
+
diff --git a/po/ru.po b/po/ru.po
index 4401714..b1d02c3 100644
--- a/po/ru.po
+++ b/po/ru.po
@@ -1,1024 +1,730 @@
-# Russian translation for PACKAGE package.
-# Copyright (C) 2014 THE PACKAGE'S COPYRIGHT HOLDER
-# This file is distributed under the same license as the PACKAGE package.
-# herrniemand, 2014.
-#
msgid ""
msgstr ""
-"Project-Id-Version: Venom\n"
-"Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2014-06-17 21:05+0200\n"
-"PO-Revision-Date: 2014-07-03 12:46+1200\n"
-"Last-Translator: Ackermann Yuriy \n"
-"Language-Team: Russian\n"
-"Language: ru\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
-"X-Generator: Poedit 1.5.4\n"
-
-#: core/ToxSession.vala:725
-#, c-format
-msgid " %s\n"
-msgstr " %s\n"
-
-#: core/DhtNode.vala:47
-msgid " (ipv6)"
-msgstr " (IPv6)"
-
-#: ui/ContactListWindow.vala:627
-#, c-format
-msgid "%F"
-msgstr "%F"
-
-#: core/Message.vala:47
-msgid "%R:%S"
-msgstr "%R:%S"
-
-#: core/GroupChat.vala:52
-#, c-format
-msgid "%i people connected"
-msgstr "%i человек подключено."
-
-#: core/GroupChat.vala:54
-#, c-format
-msgid "%i person connected"
-msgstr "%i человек подключен."
-
-#: core/Contact.vala:69 core/Contact.vala:83
-#, c-format
-msgid "%s (%s)"
-msgstr "%s (%s)"
-
-#: ui/ContactListWindow.vala:648
-#, c-format
-msgid "%s changed his name to %s\n"
-msgstr "%s сменил имя на %s\n"
-
-#: ui/ContactListWindow.vala:652
-#, c-format
-msgid "%s changed his status to %s\n"
-msgstr "%s сменил статус на %s\n"
-
-#: ui/ContactListWindow.vala:663
-#, c-format
-msgid "%s is now %s.\n"
-msgstr "%s сейчас %s.\n"
-
-#: ui/ConversationWidget.vala:60
-#, c-format
-msgid "%s is typing..."
-msgstr "%s пишет..."
-
-#: ui/ContactListWindow.vala:131
-#, c-format
-msgid "%s: %s\n"
-msgstr "%s: %s\n"
-
-#: core/DhtNode.vala:47
-#, c-format
-msgid "%s:%u%s %s"
-msgstr "%s:%u%s %s"
-
-#: ui/ContactListWindow.vala:714
-#, c-format
-msgid "'%s' has invited you to a groupchat, do you want to accept?"
-msgstr "'%s' пригласил вас в групповой чат. Принять?"
-
-#: ui/ContactListWindow.vala:577
-#, c-format
-msgid "* %s"
-msgstr "* %s"
-
-#: ui/ContactListWindow.vala:627
-#, c-format
-msgid "<%i>"
-msgstr "<%i>"
-
-#: ui/ContactListWindow.vala:627
-#, c-format
-msgid "<%s> %s:%s\n"
-msgstr "<%s> %s:%s\n"
-
-#: ui/ConversationWidget.vala:51 ui/GroupConversationWidget.vala:47
-#, c-format
-msgid "%s"
-msgstr "%s"
-
-#: ui/user_info_window.ui:119
-msgid "Tox"
-msgstr "Tox"
-
-#: ui/user_info_window.ui:282
-msgid "User"
-msgstr "Пользователь"
-
-#: core/Contact.vala:72 core/Contact.vala:86 ui/ConversationView.vala:55
-#, c-format
-msgid "%s"
-msgstr "%s"
-
-#: core/Message.vala:152 core/Message.vala:191
-msgid ""
-msgstr "<неизвестно>"
-
-#: ui/AddContactDialog.vala:76
-msgid "Add contact"
-msgstr "Добавить контакт"
+"X-Generator: POEditor.com\n"
+"Project-Id-Version: Venom\n"
+"Language: ru\n"
+"Plural-Forms: nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2);\n"
+
+#: src/core/Application.vala:32
+msgid "Set level of messages to log"
+msgstr "Установить уровень логирования"
+
+#: src/core/Application.vala:32
+msgid ""
+msgstr ""
+
+#: src/core/Application.vala:33
+msgid "Display version number"
+msgstr "Показывать номер версии"
+
+#: src/core/NotificationListener.vala:55
+msgid "New message from %s"
+msgstr "Новое сообщение от %s"
+
+#: src/core/R.vala:70
+msgid "Tox User"
+msgstr "Пользователь Tox"
+
+#: src/tox/Conference.vala:48
+msgid "%u Peers online"
+msgstr "%u пиров онлайн"
+
+#: src/view/AboutDialog.vala:53
+msgid "Packagers"
+msgstr "Упаковщиков"
+
+#: src/view/AboutDialog.vala:58
+msgid "translator-credits"
+msgstr "Ackermann Yuriy, Sorrow, Wrewolf"
+
+#: src/ui/add_contact_widget.ui:65
+#, fuzzy
+msgid "Please let me add you to my contact list. 😁"
+msgstr "Пожалуйста, добавьте меня в свой список контактов. 😁"
+
+#: src/ui/add_contact_widget.ui:108
+msgid "Send a friend request"
+msgstr "Отправить запрос другу"
+
+#: src/ui/add_contact_widget.ui:142
+msgid "_ID:"
+msgstr "_ID:"
-#: ui/ContactListWindow.vala:617
-#, c-format
-msgid "Added new friend #%i\n"
-msgstr "Добавлен новый контакт: #%i\n"
+#: src/ui/add_contact_widget.ui:159
+msgid "Enter a Tox ID or URI here"
+msgstr "Вставьте Tox ID или URI"
-#: ui/ContactListWindow.vala:1125 ui/ContactListWindow.vala:1137
-msgid "Adding Friend failed"
-msgstr "При добавлении в друзья произошла ошибка."
+#: src/ui/create_groupchat_widget.ui:122 src/ui/add_contact_widget.ui:163
+msgid "paste from clipboard"
+msgstr "вставить из буфера обмена"
-#: ui/ContactListWindow.vala:210
+#: src/ui/add_contact_widget.ui:197
+msgid "Enter your friends Tox ID"
+msgstr "Введите Tox ID друга"
+
+#: src/ui/friend_request_widget.ui:100 src/ui/add_contact_widget.ui:229
+msgid "_Message:"
+msgstr "_Сообщение:"
+
+#: src/ui/add_contact_widget.ui:255
+msgid "Send a custom message to be displayed to the friend you are adding"
+msgstr "Отправьте сообщение которое увидит друг, которого вы добавите"
+
+#: src/ui/add_contact_widget.ui:277
+msgid "Send your friend a short message"
+msgstr "Отправить другу короткое сообщение"
+
+#: src/ui/add_contact_widget.ui:308
+msgid "Send"
+msgstr "Отправить"
+
+#: src/ui/app_menu.ui:28
+#, fuzzy
+msgid "_Preferences"
+msgstr "_Настройки"
+
+#: src/ui/app_menu.ui:34
+msgid "About"
+msgstr "О программе"
+
+#: src/ui/app_menu.ui:38
+msgid "_Quit"
+msgstr "_Выход"
+
+#: src/ui/create_groupchat_widget.ui:121 src/ui/conference_info_widget.ui:61
+msgid "Conference"
+msgstr "Конференция"
+
+#: src/ui/conference_info_widget.ui:127
+msgid "Title:"
+msgstr "Заголовок:"
+
+#: src/ui/conference_info_widget.ui:266 src/ui/user_info_widget.ui:446
+#: src/ui/friend_info_widget.ui:609
+msgid "Apply"
+msgstr "Применить"
+
+#: src/ui/conference_info_widget.ui:284
+msgid "Peers"
+msgstr "Пиры"
+
+#: src/ui/conference_window.ui:103 src/ui/conversation_window.ui:292
+#: src/ui/user_info_widget.ui:277 src/ui/user_info_widget.ui:278
+#, fuzzy
+msgid "Insert Emoji"
+msgstr "Вставить смайлик"
+
+#: src/ui/contact_list_widget.ui:217
+msgid "Filter contacts by status"
+msgstr "Фильтровать контакты по статусу"
+
+#: src/ui/contact_list_widget.ui:223
msgid "All"
msgstr "Все"
-#: ui/ContactListWindow.vala:1060 ui/ContactListWindow.vala:1082
-#, c-format
-msgid "Are you sure you want to delete '%s' from your contact list?"
-msgstr "Вы уверены что хотите удалить '%s' из друзей?"
+#: src/ui/contact_list_widget.ui:331
+msgid "Add a contact"
+msgstr "Добавить контакт"
-#: core/ToxSession.vala:33
-msgid "Away"
-msgstr "Отошел"
+#: src/ui/contact_list_widget.ui:381
+#, fuzzy
+msgid "View file transfers"
+msgstr "Смотреть передачи файлов"
-#: core/ToxSession.vala:717
-#, c-format
-msgid "Background thread started.\n"
-msgstr "Запустился фоновый процесс.\n"
+#: src/ui/conversation_window.ui:37
+msgid "Start a call"
+msgstr "Позвонить"
-#: core/ToxSession.vala:756
-#, c-format
-msgid "Background thread stopped.\n"
-msgstr "Фоновый процесс упал.\n"
+#: src/ui/conversation_window.ui:317
+#, fuzzy
+msgid "Insert attachment"
+msgstr "Вставить вложение"
-#: core/Tools.vala:142
-msgid "Bad checksum"
-msgstr "Неверная контрольная сумма"
+#: src/ui/create_groupchat_widget.ui:102
+msgid "_Title:"
+msgstr "_Заголовок:"
-#: core/ToxSession.vala:35
-msgid "Busy"
-msgstr "Занят"
+#: src/ui/create_groupchat_widget.ui:188
+msgid "T_ype:"
+msgstr "_Тип:"
-#: ui/conversation_window.ui:156
-msgid "Call contact"
-msgstr "Звонить"
-
-#: ui/conversation_window.ui:174
-msgid "Call contact with video"
-msgstr "Звонок с видео"
-
-#: core/Tools.vala:158 core/Tools.vala:171
-#, c-format
-msgid "Can't create action regex: %s.\n"
-msgstr "Не удалось выполнить регулярное выражение: %s.\n"
-
-#: core/SqliteTools.vala:75
-#, c-format
-msgid "Can't open database: %d: %s\n"
-msgstr "Не могу открыть базу данных : %d: %s\n"
-
-#: core/Tools.vala:136
-msgid "Can't send to own key"
-msgstr "Нельзя отправить сообщение себе самому."
-
-#: ui/FileTransferChatEntry.vala:119
-msgid "Canceled"
-msgstr "Отменено"
-
-#: ui/contact_list.ui:72
-msgid "Change _Status"
-msgstr "Изменить _Статус"
-
-#: ui/ContactListWindow.vala:670
-msgid "Connected to the network"
-msgstr "Подключен"
-
-#: core/ToxSession.vala:720
-#, c-format
-msgid "Connecting to DHT Nodes:\n"
-msgstr "Подключение к DHT нодам:\n"
-
-#: ui/ContactListWindow.vala:668
-#, c-format
-msgid "Connection to DHT %s.\n"
-msgstr "Подключение к DHT %s.\n"
-
-#: ui/ContactListWindow.vala:907
-#, c-format
-msgid "Contact accepted file sending request\n"
-msgstr "Началась передача файла контакту.\n"
-
-#: ui/ContactListWindow.vala:508
-#, c-format
-msgid "Copied Tox ID to clipboard\n"
-msgstr "Tox ID скопирован в буфер обмена.\n"
-
-#: ui/ContactListWindow.vala:1135
-#, c-format
-msgid "Could not add friend: %s.\n"
-msgstr "Не удалось добавить друга: %s.\n"
-
-#: ui/ContactListWindow.vala:1123
-msgid "Could not add friend: Invalid ID\n"
-msgstr "Не удалось добавить друга: Недействительный ID.\n"
-
-#: core/SqliteTools.vala:40
-#, c-format
-msgid "Could not bind int to %s."
-msgstr "Не удалось привязать int к %s."
-
-#: core/SqliteTools.vala:50
-#, c-format
-msgid "Could not bind int64 to %s."
-msgstr "Не удалось привязать int64 к %s."
-
-#: core/SqliteTools.vala:60
-#, c-format
-msgid "Could not bind text to %s"
-msgstr "Не удалось привязать текст к %s."
-
-#: ui/ContactListWindow.vala:447
-#, c-format
-msgid "Could not change user name!\n"
-msgstr "Не удалось изменить имя.\n"
-
-#: ui/ContactListWindow.vala:455
-#, c-format
-msgid "Could not change user statusmessage!\n"
-msgstr "Не удалось изменить статус.\n"
-
-#: ui/ContactListWindow.vala:1189
-#, c-format
-msgid "Could not create a new groupchat.\n"
-msgstr "Не удалось создать групповой чай.\n"
-
-#: ui/ContactListWindow.vala:725
-#, c-format
-msgid "Could not join groupchat.\n"
-msgstr "Не удалось подключиться к групповому чату.\n"
-
-#: ui/ContactListWindow.vala:146
-#, c-format
-msgid "Could not load session data (%s), creating new one.\n"
-msgstr "Не удалось загрузить сессию (%s). Создаю новую сессию.\n"
-
-#: ui/ContactListWindow.vala:130
-#, c-format
-msgid "Could not read theme from \"%s\""
-msgstr "Не удалось загрузить тему из \"%s\""
-
-#: ui/ContactListWindow.vala:1090
-#, c-format
-msgid "Could not remove %s.\n"
-msgstr "Не удалось удалить %s.\n"
-
-#: ui/ContactListWindow.vala:1068
-#, c-format
-msgid "Could not remove contact %i.\n"
-msgstr "Не удалось удалить контакт %i.\n"
-
-#: core/ToxSession.vala:352
-#, c-format
-msgid "Could not remove peer [%i] from groupchat #%i (no such peer)\n"
-msgstr ""
-"Не удалось удалить пир [%i] из группового чата #%i (несуществующий пир)\n"
+#: src/ui/create_groupchat_widget.ui:282
+msgid "Create"
+msgstr "Создать"
-#: ui/ContactListWindow.vala:1112
-msgid "Could not resolve ID from DNS record\n"
-msgstr ""
-"Не удалось \n"
-" Impossibile risolvere il Tox ID dal record DNS\n"
-
-#: ui/contact_list.ui:416
-msgid "Create groupchat"
-msgstr "Создать групповой чат"
-
-#: ui/settings_window.ui:301
-msgid "Default Tox DNS ID suffix:"
-msgstr "Стандартный DNS ID суфикс:"
-
-#: ui/FileTransferChatEntry.vala:125 ui/FileTransferChatEntry.vala:129
-msgid "Disconnected"
-msgstr "Отключен"
-
-#: ui/ContactListWindow.vala:673
-msgid "Disconnected from the network"
-msgstr "Отключен от сети"
-
-#: ui/UserInfoWindow.vala:86
-msgid "Edit user information"
-msgstr "Профиль"
-
-#: ui/ContactListWindow.vala:899
-#, c-format
-msgid "Ended file transfer for %s to %s\n"
-msgstr "Законченна передача файла от %s к %s\n"
-
-#: ui/ContactListWindow.vala:102
-#, c-format
-msgid "Ending session...\n"
-msgstr "Закрываю сеанс...\n"
-
-#: ui/add_contact_dialog.ui:40
-msgid "Enter a Tox ID here or a Tox URI"
-msgstr "Вставьте Tox ID или Tox URI"
-
-#: core/ContactStorage.vala:108
-#, c-format
-msgid "Error creating contacts insert statement: %d: %s\n"
-msgstr "Errore nel creare lo statement di inserimento contatti: %d: %s\n"
-
-#: core/ContactStorage.vala:113
-#, c-format
-msgid "Error creating contacts select statement: %d: %s\n"
-msgstr "Errore nel creare lo statement di selezione contatti: %d: %s\n"
-
-#: core/ContactStorage.vala:103
-#, c-format
-msgid "Error creating contacts table: %s\n"
-msgstr "Ошибка при попытке создания таблицы контактов: %s\n"
-
-#: core/DhtNodeStorage.vala:177
-#, c-format
-msgid "Error creating dht nodes insert statement: %d: %s\n"
-msgstr "Errore nel creare lo statement di inserimento server DHT: %d: %s\n"
-
-#: core/DhtNodeStorage.vala:182
-#, c-format
-msgid "Error creating dht nodes select statement: %d: %s\n"
-msgstr "Errore nel create lo statement di selezione server DHT: %d: %s\n"
-
-#: core/DhtNodeStorage.vala:172
-#, c-format
-msgid "Error creating dht nodes table: %s\n"
-msgstr "Ошибка при создании таблицы DHT нод: %s\n"
-
-#: core/ToxDns.vala:36
-#, c-format
-msgid "Error creating tox dns regex: %s\n"
-msgstr "Не удалось создать tox DNS регулярное выражение: %s\n"
-
-#: core/ToxDns.vala:51
-#, c-format
-msgid "Error creating tox uri regex: %s\n"
-msgstr "Не удалось создать tox URI регулярное выражение: %s\n"
-
-#: ui/ConversationTextView.vala:184
-#, c-format
-msgid "Error matching uri regex: %s\n"
-msgstr "Ошибка не совпадения регулярного выражения URI: %s\n"
-
-#: ui/ConversationWidget.vala:308
-#, c-format
-msgid "Error occured while getting file size: %s"
-msgstr "Ошибка при попытке получения размера файла: %s"
-
-#: core/ToxSession.vala:111
-#, c-format
-msgid "Error opening database: %s\n"
-msgstr "Ошибка при попытке открытии базы данных: %s\n"
-
-#: core/Settings.vala:112
-#, c-format
-msgid "Error reading configs:%s\n"
-msgstr "Ошибка при попытке чтения настроек: %s\n"
-
-#: core/ToxDns.vala:81
-#, c-format
-msgid "Error resolving name: %s\n"
-msgstr "Ошибка извлечения имени: %s\n"
-
-#: core/MessageLog.vala:135
-#, c-format
-msgid "Error retrieving logs from sqlite database: %s\n"
-msgstr "Ошибка при попытке получении логов sqlite базы данных: %s\n"
-
-#: core/Settings.vala:99
-#, c-format
-msgid "Error saving configs:%s\n"
-msgstr "Ошибка при попытке сохранении настроек: %s\n"
-
-#: core/Tools.vala:123
-#, c-format
-msgid "Error when doing uri markup: %s"
-msgstr "Ошибка разметки URI: %s"
-
-#: ui/ConversationTextView.vala:245
-#, c-format
-msgid "Error when showing uri: %s\n"
-msgstr "Ошибка отображения URI: %s\n"
-
-#: ui/ContactListWindow.vala:168
-#, c-format
-msgid "Error while loading icon: %s\n"
-msgstr "Ошибка при загрузке иконки: %s\n"
-
-#: core/ResourceFactory.vala:126
-#, c-format
-msgid "Error while loading image from \"%s\":%s\n"
-msgstr "Ошибка при загрузке изображения из: \"%s\": %s\n"
-
-#: core/ToxSession.vala:801
-msgid "Error while loading messenger data."
-msgstr "Ошибка при загрузке данных мессенджера."
-
-#: core/ToxSession.vala:795
-msgid "Error while reading from stream."
-msgstr "Ошибка при чтении из потока."
-
-#: ui/FileTransferChatEntry.vala:171
-#, c-format
-msgid "Error while trying to create file: %s\n"
-msgstr "Ошибка при попытке создания файла: %s\n"
-
-#: ui/ContactListWindow.vala:961
-#, c-format
-msgid "Error while trying to write data to file\n"
-msgstr "Ошибка при попытке записи данных в файл.\n"
-
-#: core/ToxSession.vala:828
-msgid "Error while writing to stream."
-msgstr "Ошибка при записи в поток."
-
-#: core/ContactStorage.vala:88
-#, c-format
-msgid "Error writing contact to sqlite database: %s\n"
-msgstr "Ошибка при записи контакта в sqlite базу данных: %s\n"
-
-#: core/MessageLog.vala:118
-#, c-format
-msgid "Error writing message to sqlite database: %s\n"
-msgstr "Ошибка при записи сообщения в sqlite базу данных: %s\n"
-
-#: core/MessageLog.vala:186 core/MessageLog.vala:193
-#, c-format
-msgid "Error: %d: %s\n"
-msgstr "Ошибка: %d: %s\n"
-
-#: core/MessageLog.vala:169 core/MessageLog.vala:179
-#: ui/ConversationView.vala:78
-#, c-format
-msgid "Error: %s\n"
-msgstr "Ошибка %s\n"
-
-#: core/ToxSession.vala:788
-#, c-format
-msgid "File \"%d\" does not exist."
-msgstr "Файл \"%d\" не существует."
-
-#: ui/ContactListWindow.vala:929
-#, c-format
-msgid "File transfer finished for file number %u"
-msgstr "Отправка была завершена для %u файлов."
-
-#: ui/ContactListWindow.vala:925
-#, c-format
-msgid "File transfer was rejected for file number %u"
-msgstr "%u файлов было отклонено."
-
-#: ui/FileTransferChatEntry.vala:94
-msgid "File was rejected"
-msgstr "Пользователь отклонил прием файла."
-
-#: ui/settings_window.ui:236
-msgid "Flash window when a new message arrives"
-msgstr "Оповещать о приходе нового сообщения."
-
-#: ui/ContactListWindow.vala:614
-#, c-format
-msgid "Friend could not be added.\n"
-msgstr "Контакт не может быть добавлен.\n"
-
-#: core/Tools.vala:138
-msgid "Friend request already sent"
-msgstr "Запрос на добавление в контакта уже был отправлен."
-
-#: core/Tools.vala:148
-msgid "Friend request successfully sent"
-msgstr "Запрос на добавление в контакта отправлен."
-
-#: ui/ContactListWindow.vala:1142
-#, c-format
-msgid "Friend request successfully sent. Friend added as %i.\n"
-msgstr "Запрос на добавление в контакта отправлен. Контакт добавлен как %i.\n"
-
-#: ui/ContactListWindow.vala:771
-#, c-format
-msgid "Group action from unknown contact #%i [%i]\n"
-msgstr "Групповое действие от неизвестного контакта: #%i [%i]\n"
-
-#: ui/ContactListWindow.vala:708
-#, c-format
-msgid "Group invite from %s with public key %s\n"
-msgstr "Группа пригласила %s, с публичным ключом %s\n"
-
-#: ui/ContactListWindow.vala:742
-#, c-format
-msgid "Group message from unknown contact #%i [%i]\n"
-msgstr "Групповое сообщение от неизвестного контакта: #%i [%i]\n"
-
-#: core/GroupChat.vala:45
-#, c-format
-msgid "Groupchat #%i"
-msgstr "Групповой чат #%i"
-
-#: ui/ContactListWindow.vala:896
-#, c-format
-msgid "I/O error while trying to close file stream: %s\n"
-msgstr "Ошибка I/O при попытке закрыть файловый поток: %s\n"
-
-#: ui/ContactListWindow.vala:888
-#, c-format
-msgid "I/O error while trying to read file: %s\n"
-msgstr "Ошибка I/O при попытке чтения файла: %s\n"
-
-#: ui/AddContactDialog.vala:96
-msgid "ID contains invalid characters"
-msgstr "ID содержит недопустимые символы."
-
-#: ui/user_info_window.ui:40
+#: src/view/FileTransferWidget.vala:39 src/ui/file_transfer_widget.ui:57
+#, fuzzy
+msgid "File transfers"
+msgstr "Передачи файлов"
+
+#: src/ui/friend_info_widget.ui:171
+msgid "Remove from your friends list"
+msgstr "Удалить из списка друзей"
+
+#: src/ui/user_info_widget.ui:213
+msgid "Username:"
+msgstr "Имя пользователя:"
+
+#: src/ui/friend_info_widget.ui:222
+msgid "Alias:"
+msgstr "Псевдоним:"
+
+#: src/ui/friend_info_widget.ui:254
+msgid "Set a custom alias to quickly find your friends"
+msgstr "Установите пользовательский псевдоним, чтобы быстро найти своих друзей"
+
+#: src/ui/user_info_widget.ui:319 src/ui/friend_info_widget.ui:520
+msgid "Tox"
+msgstr "Tox"
+
+#: src/ui/user_info_widget.ui:352
msgid "ID:"
msgstr "ID:"
-#: ui/ContactListWindow.vala:86
-#, c-format
-msgid "ID: %s\n"
-msgstr "ID: %s\n"
+#: src/ui/message_widget.ui:110
+msgid "Message sent ✓"
+msgstr "Сообщение отправлено ✓"
-#: ui/user_info_window.ui:222
-msgid "Icon:"
-msgstr "Иконка:"
+#: src/ui/message_widget.ui:126
+msgid "Message received ✓"
+msgstr "Сообщение получено ✓"
-#: core/SqliteTools.vala:37 core/SqliteTools.vala:47 core/SqliteTools.vala:57
-#, c-format
-msgid "Index for %s not found."
-msgstr "Индекс для %s не найден."
+#. This is shown on peers in groupchats, if you have them also added to your friends
+#: src/ui/peer_entry_compact.ui:53 src/ui/peer_entry.ui:77
+msgid "This peer is also in your friends list"
+msgstr "Этот пир также находится в вашем списке друзей"
-#: ui/conversation_window.ui:290
-msgid "Insert Smiley"
-msgstr "Вставить смайлик"
+#: src/ui/settings_widget.ui:78
+msgid "General"
+msgstr "Основные"
-#: core/ToxDns.vala:113
-#, c-format
-msgid "Invalid record\n"
-msgstr "Неверная запись DNS.\n"
+#: src/ui/settings_widget.ui:251
+msgid "Appearance"
+msgstr "Внешний вид"
-#: core/ToxDns.vala:64
-#, c-format
-msgid "Invalid tox uri\n"
-msgstr "Неправильный URI.\n"
+#: src/ui/settings_widget.ui:296
+msgid "Dark Theme"
+msgstr "Темная тема"
-#: ui/ContactListWindow.vala:728
-#, c-format
-msgid "Joined Groupchat #%i\n"
-msgstr "Присоединился к групповому чату #%i\n"
+#: src/ui/settings_widget.ui:506
+msgid "Minimize to tray"
+msgstr "Свернуть в трей"
-#: ui/settings_window.ui:18
-msgid "KB/MB"
-msgstr "Кбайт/Мбайт"
+#: src/ui/settings_widget.ui:603
+msgid "Privacy"
+msgstr "Приватность"
-#: ui/settings_window.ui:78
-msgid "Keep history"
-msgstr "Сохранять историю"
+#: src/ui/settings_widget.ui:647
+msgid "Send typing notifications"
+msgstr "Отправлять уведомления о наборе текста"
-#: ui/settings_window.ui:14
-msgid "KiB/MiB"
-msgstr "KiB/MiB"
+#: src/ui/settings_widget.ui:660
+msgid "Show others when I am typing"
+msgstr "Показывать остальным когда я печатаю"
-#: core/Contact.vala:117
-#, c-format
-msgid "Last seen: %s"
-msgstr "Был онлайн: %s"
+#: src/ui/settings_widget.ui:744
+msgid "History"
+msgstr "История"
-#: ui/AddContactDialog.vala:53
-#, c-format
-msgid "Loading add contact window failed!\n"
-msgstr "Не удалось загрузить окно контактов!\n"
+#: src/ui/settings_widget.ui:879
+msgid "days"
+msgstr "дни"
-#: ui/ConversationWidget.vala:71 ui/SettingsWindow.vala:32
-#, c-format
-msgid "Loading conversation window failed!\n"
-msgstr "Не удалось загрузить окно чатов!\n"
+#: src/ui/settings_widget.ui:910
+msgid "Delete all previous conversations"
+msgstr "Удалить все предыдущие разговоры"
-#: ui/FileTransferChatEntry.vala:40
-#, c-format
-msgid "Loading message widget failed!\n"
-msgstr "Не удалось загрузить виджет чата!\n"
+#: src/ui/settings_widget.ui:1328
+msgid "Update bootstrap nodes"
+msgstr "Обновление узлов начальной загрузки"
-#: core/Tools.vala:132
-msgid "Message too long"
-msgstr "Размер сообщения превышает максимально допустимый размер."
+#: src/ui/user_info_widget.ui:394
+msgid "Copy to clipboard"
+msgstr "Скопировать в буфер обмена"
-#: ui/settings_window.ui:337
-msgid "Miscellaneous"
-msgstr "Разное"
+#: src/ui/welcome_widget.ui:62
+msgid "A new kind of instant messaging"
+msgstr "Новый вид обмена мгновенными сообщениями"
-#: ui/user_info_window.ui:192
-msgid "Name:"
-msgstr "Имя:"
+#: src/ui/welcome_widget.ui:78
+msgid "Chat with your friends and family without anyone else listening in."
+msgstr "Общайтесь со своими друзьями и семьей, не слушая других."
-#: ui/ContactListWindow.vala:604
-#, c-format
-msgid ""
-"New friend request from '%s'.\n"
-"Do you want to accept?"
-msgstr ""
-"'%s' хочет добавить вас в друзья.\n"
-"Принять?"
+#: src/ui/welcome_widget.ui:131
+msgid "Learn more"
+msgstr "Узнать больше"
-#: ui/AddContactDialog.vala:90
-msgid "No ID given"
-msgstr "ID не был предоставлен."
+#: src/core/Message.vala:79 src/viewmodel/MessageViewModel.vala:86
+#: src/tox/ConferenceMessage.vala:56
+msgid "me"
+msgstr "меня"
-#: core/Tools.vala:134
-msgid "No message included"
-msgstr "Сообщение не было предоставлено."
+#: src/ui/user_info_widget.ui:110
+msgid "Choose an avatar"
+msgstr "Выберите аватар"
-#: core/ToxDns.vala:103
-#, c-format
-msgid "No pin privided, aborting...\n"
-msgstr "Пин-код не был предоставлен, прерываю процесс...\n"
+#: src/ui/friend_request_widget.ui:168
+msgid "Reject request"
+msgstr "Отклонить запрос"
-#: ui/contact_list.ui:118
-msgid "O_ffline"
-msgstr "Не в сети"
+#: src/ui/friend_request_widget.ui:192
+msgid "Accept request"
+msgstr "Принять запрос"
+
+#: src/core/NotificationListener.vala:76
+msgid "New file from %s"
+msgstr "Новый файл от %s"
+
+#: src/viewmodel/ContactListEntryViewModel.vala:58
+msgid "New Message!"
+msgstr "Новое сообщение!"
-#: core/Contact.vala:98 core/Contact.vala:108 core/ToxSession.vala:37
+#: src/viewmodel/ContactListEntryViewModel.vala:64
msgid "Offline"
msgstr "Не в сети"
-#: core/GroupChatContact.vala:32 core/ToxSession.vala:31
-#: ui/ContactListWindow.vala:208
+#: src/viewmodel/ContactListEntryViewModel.vala:72
+#: src/ui/user_status_menu.ui:34
+msgid "Away"
+msgstr "Отошел"
+
+#: src/viewmodel/ContactListEntryViewModel.vala:74
+#: src/ui/user_status_menu.ui:40
+msgid "Busy"
+msgstr "Занят"
+
+#: src/viewmodel/ContactListEntryViewModel.vala:76
+#: src/ui/user_status_menu.ui:28
msgid "Online"
msgstr "В сети"
-#: ui/contact_list.ui:449
-msgid "Open preferences"
-msgstr "Настройки"
+#: src/core/TimeStamp.vala:40
+msgid "Today at %s"
+msgstr "Сегодня в %s"
+
+#: src/core/TimeStamp.vala:44
+msgid "Yesterday at %s"
+msgstr "Вчера в %s"
+
+#: src/tox/Conference.vala:44
+msgid "Unnamed conference %u"
+msgstr "Безымянная конференция %u"
+
+#: src/tox/ToxSession.vala:657
+msgid "Address must consist of 76 hexadecimal characters"
+msgstr "Адрес должен состоять из 76 шестнадцатеричных символов"
+
+#: src/view/ConversationWindow.vala:227 src/view/FileTransferEntry.vala:86
+#, fuzzy
+msgid "_Cancel"
+msgstr "О_тмена"
+
+#: src/view/ConversationWindow.vala:226
+msgid "_Open"
+msgstr "_Открыть"
+
+#: src/view/FileTransferEntry.vala:85
+msgid "_Save"
+msgstr "_Сохранить"
+
+#: src/ui/file_transfer_widget.ui:140
+#, fuzzy
+msgid "No file transfers yet …"
+msgstr "Ещё нет передач файлов..."
+
+#: src/ui/file_transfer_entry.ui:56 src/ui/file_transfer_entry_inline.ui:62
+#, fuzzy
+msgid "Remove transfer"
+msgstr "Удалить передачу"
+
+#: src/ui/file_transfer_entry.ui:124 src/ui/file_transfer_entry_inline.ui:130
+msgid "Open file"
+msgstr "Открыть файл"
+
+#: src/ui/file_transfer_entry.ui:148 src/ui/file_transfer_entry_inline.ui:154
+#, fuzzy
+msgid "Start transfer"
+msgstr "Начать передачу"
+
+#: src/ui/file_transfer_entry.ui:169 src/ui/file_transfer_entry_inline.ui:175
+#, fuzzy
+msgid "Pause transfer"
+msgstr "Приостановить передачу"
+
+#: src/ui/file_transfer_entry.ui:190 src/ui/file_transfer_entry_inline.ui:196
+#, fuzzy
+msgid "Stop transfer"
+msgstr "Остановить передачу"
+
+#: src/ui/create_groupchat_widget.ui:212
+msgid "Text"
+msgstr "Текст"
+
+#: src/ui/create_groupchat_widget.ui:228
+msgid "Speech"
+msgstr "Речь"
+
+#: src/ui/peer_entry_compact.ui:39 src/ui/peer_entry.ui:90
+msgid "That's you"
+msgstr "Это Вы"
+
+#: src/ui/welcome_widget.ui:178
+#, fuzzy
+msgid "Get involved"
+msgstr "Поучаствовать"
+
+#: src/ui/settings_widget.ui:161
+msgid "Proxy"
+msgstr "Прокси"
+
+#: src/ui/settings_widget.ui:309
+msgid "Use a dark variant of the theme"
+msgstr "Использовать тёмный вариант темы"
+
+#: src/ui/settings_widget.ui:366
+msgid "Animations"
+msgstr "Анимации"
+
+#: src/ui/settings_widget.ui:379
+msgid "Enable animated transitions"
+msgstr "Включить анимированные переходы"
+
+#: src/ui/settings_widget.ui:436
+msgid "Notifications"
+msgstr "Уведомления"
+
+#: src/ui/settings_widget.ui:449
+msgid "Show notifications for unread messages"
+msgstr "Показывать уведомления о непрочитанных сообщениях"
+
+#: src/ui/settings_widget.ui:519
+msgid "Minimize app to system tray on close"
+msgstr "Сворачивать приложение в трей при закрытии"
+
+#: src/ui/settings_widget.ui:809
+msgid "Keep forever"
+msgstr "Хранить вечно"
+
+#: src/ui/settings_widget.ui:846
+msgid "Remove older than"
+msgstr "Удалить старше чем"
+
+#: src/ui/settings_widget.ui:1004
+msgid "Connection"
+msgstr "Соединение"
+
+#: src/ui/settings_widget.ui:1047
+msgid "UDP"
+msgstr "UDP"
+
+#: src/ui/settings_widget.ui:1117
+msgid "IPv6"
+msgstr "IPv6"
+
+#: src/ui/settings_widget.ui:1130
+msgid "Allow both IPv4 and IPv6 communication"
+msgstr "Использовать и IPv4 и IPv6"
+
+#: src/ui/settings_widget.ui:1187
+msgid "Local discovery"
+msgstr "Обнаружение локальных устройств"
+
+#: src/ui/settings_widget.ui:1200
+msgid "Look for peers on the local network"
+msgstr "Искать пиры в локальной сети"
+
+#: src/ui/settings_widget.ui:1257
+msgid "Hole punching"
+msgstr "Пробитие NAT"
+
+#: src/ui/settings_widget.ui:1270
+msgid "Enable UDP hole punching"
+msgstr "Включить UDP пробитие NAT"
+
+#: src/ui/settings_widget.ui:1364
+msgid "Bootstrap nodes"
+msgstr "Узлы начальной загрузки"
+
+#: src/ui/settings_widget.ui:1500
+msgid "Proxy"
+msgstr "Прокси"
+
+#: src/ui/settings_widget.ui:1567
+msgid "System settings"
+msgstr "Системные настройки"
+
+#: src/ui/settings_widget.ui:1580
+msgid "Use your systems proxy settings"
+msgstr "Использовать системные настройки прокси"
+
+#: src/ui/settings_widget.ui:1634
+msgid "Manual settings"
+msgstr "Ручные настройки"
+
+#: src/ui/settings_widget.ui:1647
+#, fuzzy
+msgid "Use custom proxy settings"
+msgstr "Пользовательские настройки прокси"
+
+#: src/ui/settings_widget.ui:1688
+msgid "Host"
+msgstr "Хост"
+
+#: src/ui/settings_widget.ui:1728
+msgid "Set a SOCKS5 proxy to connect to"
+msgstr "Указать SOCKS5 прокси для подключения"
+
+#: src/ui/friend_info_widget.ui:242
+#, fuzzy
+msgid "Reset alias"
+msgstr "Сбросить псевдоним"
+
+#: src/ui/friend_info_widget.ui:364
+msgid "Auto accept conference invites"
+msgstr "Автоматически принимать приглашения в конференции"
+
+#: src/ui/friend_info_widget.ui:411
+#, fuzzy
+msgid "Auto accept file transfers"
+msgstr "Автоматически принимать передачи файлов"
-#: core/Tools.vala:146
-msgid "Out of memory"
-msgstr "Нехватка памяти"
+#: src/ui/friend_info_widget.ui:455
+msgid "Save files to"
+msgstr "Сохранять файлы в"
-#: ui/FileTransferChatEntry.vala:104
-msgid "Paused"
-msgstr "Приостановлен"
+#: src/viewmodel/ContactListViewModel.vala:102
+msgid "New conference…"
+msgstr ""
-#: ui/PinDialog.vala:37
-#, c-format
-msgid ""
-"Please insert PIN for \n"
-"%s"
+#: src/viewmodel/ContactListViewModel.vala:115
+msgid "Invite to conference"
msgstr ""
-"Пожалуйста введите Пин-код для \n"
-"%s"
-#: ui/PinDialog.vala:49
-msgid "Please insert PIN..."
-msgstr "Пожалуйста введите Пин-код..."
+#: src/viewmodel/ContactListViewModel.vala:118 src/ui/conference_window.ui:137
+#: src/ui/conversation_window.ui:86
+msgid "Show details"
+msgstr ""
-#: ui/add_contact_dialog.ui:6
-msgid "Please let me add you to my contact list."
-msgstr "Пожалуйста, добавьте меня в свой список контактов."
+#: src/viewmodel/ContactListViewModel.vala:140
+msgid "%u new friend request"
+msgid_plural "%u new friend requests"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+
+#: src/viewmodel/ContactListViewModel.vala:148
+msgid "%u new conference invite"
+msgid_plural "%u new conference invites"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+
+#: src/core/TimeStamp.vala:26
+msgid "Just now"
+msgstr ""
-#: ui/settings_window.ui:221
-msgid "Privacy"
-msgstr "Приватность"
+#: src/core/TimeStamp.vala:31
+msgid "%u minute ago"
+msgid_plural "%u minutes ago"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+
+#: src/core/TimeStamp.vala:36
+msgid "%u hour ago"
+msgid_plural "%u hours ago"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+
+#: src/ui/create_groupchat_widget.ui:68 src/ui/contact_list_widget.ui:356
+msgid "Create a conference"
+msgstr ""
-#: ui/ContactListWindow.vala:869
-#, c-format
-msgid "Read incorrect number of bytes from file\n"
-msgstr "Прочитано неправильно количество байт из файла.\n"
+#: src/ui/create_groupchat_widget.ui:156
+msgid "Name the conference (optional)"
+msgstr ""
-#: ui/FileTransferChatEntry.vala:113
-msgid "Receiving failed"
-msgstr "Ошибка при получении."
+#: src/ui/create_groupchat_widget.ui:252
+msgid "Select a conference type"
+msgstr ""
-#: ui/ContactListWindow.vala:1114
-msgid "Resolving ID failed"
-msgstr "Ошибка при получении ID."
+#: src/ui/create_groupchat_widget.ui:299
+msgid "New conference"
+msgstr ""
-#: ui/ContactListWindow.vala:427
-#, c-format
-msgid "Retrieved contact %s from savefile.\n"
-msgstr "Контакт %s был успешно извлечен из сохранения.\n"
+#: src/ui/create_groupchat_widget.ui:312 src/ui/create_groupchat_widget.ui:346
+msgid "Conference invites"
+msgstr ""
-#: Main.vala:50
-#, c-format
-msgid "Run '%s --help' to see a full list of available command line options.\n"
+#: src/ui/create_groupchat_widget.ui:408
+msgid "No new conference invites"
msgstr ""
-"Используйте '%s --help' чтобы увидеть полный список доступных параметров "
-"командной строки.\n"
-
-#: core/MessageLog.vala:86
-#, c-format
-msgid "SQLite database closed.\n"
-msgstr "Удалена SQLita база данных.\n"
-
-#: core/MessageLog.vala:82
-#, c-format
-msgid "SQLite database created.\n"
-msgstr "Создана SQLite база данных.\n"
-
-#: ui/FileTransferChatEntry.vala:158
-msgid "Save"
-msgstr "Сохранить"
-
-#: ui/FileTransferChatEntry.vala:155
-msgid "Save file"
-msgstr "Сохранить файл"
-
-#: ui/ContactListWindow.vala:120
-#, c-format
-msgid "Saving session file failed: %s\n"
-msgstr "Ошибка при сохранении файла сессии: %s\n"
-
-#: ui/FileTransferChatEntry.vala:165
-#, c-format
-msgid "Saving to: %s\n"
-msgstr "Сохраняю в: %s\n"
-
-#: ui/ContactListWindow.vala:116
-#, c-format
-msgid "Saving tox session data\n"
-msgstr "Сохраняю данные сеанса\n"
-
-#: ui/ConversationWidget.vala:282
-msgid "Select"
-msgstr "Выбрано"
-
-#: ui/ConversationWidget.vala:279
-msgid "Select a file to send"
-msgstr "Выберите файл для отправки"
-
-#: ui/add_contact_dialog.ui:113
-msgid "Send a custom message to be displayed to the friend you are adding"
-msgstr "Отправьте сообщение которое уви"
-#: ui/conversation_window.ui:308
-msgid "Send file"
-msgstr "Отправить файл"
+#: src/ui/conversation_window.ui:62
+msgid "Start a video call"
+msgstr ""
-#: ui/conversation_window.ui:341
-msgid "Send message"
-msgstr "Отправить сообщение"
+#: src/ui/friend_request_widget.ui:66
+msgid "_Public key:"
+msgstr ""
-#: ui/FileTransferChatEntry.vala:107
-msgid "Sending failed"
-msgstr "Отправка не удалась"
+#: src/ui/conference_info_widget.ui:78
+msgid "Leave Conference"
+msgstr ""
-#: ui/ContactListWindow.vala:111
-#, c-format
-msgid "Session ended gracefully.\n"
-msgstr "Сессия закончилась изящно.\n"
+#: src/ui/conference_info_widget.ui:196 src/ui/friend_info_widget.ui:291
+msgid "Show notifications"
+msgstr ""
+
+#: src/ui/conference_info_widget.ui:234 src/ui/friend_info_widget.ui:330
+msgid "Notifications have been globally disabled"
+msgstr ""
+
+#: src/ui/conference_invite_entry.ui:65
+msgid "Invite from:"
+msgstr ""
+
+#: src/ui/conference_invite_entry.ui:109
+msgid "Accept invite"
+msgstr ""
+
+#: src/ui/conference_invite_entry.ui:133
+msgid "Reject invite"
+msgstr ""
+
+#: src/ui/add_contact_widget.ui:52
+msgid "No new friend requests"
+msgstr ""
+
+#: src/ui/contact_list_widget.ui:56 src/ui/add_contact_widget.ui:325
+msgid "Add a friend"
+msgstr ""
+
+#: src/ui/add_contact_widget.ui:338 src/ui/add_contact_widget.ui:372
+msgid "Friend requests"
+msgstr ""
+
+#: src/ui/user_info_widget.ui:258
+msgid "Status message:"
+msgstr ""
-#: ui/add_contact_dialog.ui:67
-msgid "Set a custom nickname for the friend you are about to add"
-msgstr "Назначить ник для пользователя которого вы собираетесь добавить."
+#: src/ui/settings_widget.ui:1060
+msgid "Use UDP communication when available"
+msgstr ""
-#: core/Tools.vala:144
-msgid "Set new nospam"
-msgstr "Установить новый NoSpam"
+#: src/view/WelcomeWidget.vala:39
+msgid "A new kind of instant messaging"
+msgstr ""
-#: ui/settings_window.ui:30
+#: src/view/SettingsWidget.vala:69
msgid "Settings"
-msgstr "Настройки"
+msgstr ""
-#: core/Settings.vala:102
-#, c-format
-msgid "Settings saved.\n"
-msgstr "Настройки успешно сохранены.\n"
+#: src/ui/conference_window.ui:216 src/ui/conversation_window.ui:129
+msgid "No messages yet..."
+msgstr ""
-#: ui/settings_window.ui:186
-msgid "Show _others when I am typing"
-msgstr "Показывать остальным когда я печатаю."
+#: src/ui/contact_list_widget.ui:406
+msgid "Open settings"
+msgstr ""
-#: ui/settings_window.ui:258
-msgid "Show filesize in"
-msgstr "Показать размер файла в"
+#: src/ui/contact_list_widget.ui:448
+msgid "Edit your profile"
+msgstr ""
-#: ui/settings_window.ui:202
-msgid "Show me when others are typing"
-msgstr "Показывать мне когда остальные печатают."
+#: src/ui/contact_list_widget.ui:476
+msgid "Change your status"
+msgstr ""
-#: Main.vala:70
-#, c-format
-msgid "Starting in offline mode\n"
-msgstr "Старт в офлайн режиме.\n"
+#: src/ui/friend_info_widget.ui:554
+msgid "Public key:"
+msgstr ""
-#: ui/user_info_window.ui:178
-msgid "Status message:"
-msgstr "Статус:"
+#: src/view/ConversationWindow.vala:223
+msgid "Choose a file to send"
+msgstr ""
-#: ui/ContactListWindow.vala:408
-#, c-format
-msgid "Theme refreshed\n"
-msgstr "Тема была успешно обновлена.\n"
+#: src/view/UserInfoWidget.vala:56
+msgid "Images"
+msgstr ""
-#: ui/Client.vala:116
-msgid "There is currently no help available"
-msgstr "Функция \"Помощь\" не доступна в данный момент."
+#: src/ui/user_info_widget.ui:62
+msgid "Reset"
+msgstr ""
-#: core/ResourceFactory.vala:77
-msgid "Tox User"
-msgstr "Tox пользователь"
-
-#: core/ResourceFactory.vala:78
-#, c-format
-msgid "Toxing on Venom v.%s"
-msgstr "Toxing on Venom v.%s"
-
-#: ui/ContactListWindow.vala:826
-#, c-format
-msgid "Trying to send unknown file"
-msgstr "Попытка отправить неизвестный файл"
-
-#: ui/MessageTextView.vala:27
-msgid "Type your message here..."
-msgstr "Сообщение..."
-
-#: core/Tools.vala:140
-msgid "Unknown error"
-msgstr "Неизвестная ошибка"
-
-#: ui/ContactListWindow.vala:890
-#, c-format
-msgid "Unknown error while trying to read file: %s\n"
-msgstr "Неизвестная ошибка при попытке чтения файла: %s\n"
-
-#: Main.vala:65
-#, c-format
-msgid "Using Gtk.TextView to display messages\n"
-msgstr "Использую Gtk.TextView для отображения сообщений.\n"
-
-#: Main.vala:60
-#, c-format
-msgid "Using data file \"%s\"\n"
-msgstr "Использую дата-файл: \"%s\"\n"
-
-#: ui/AddContactDialog.vala:100
-msgid "Valid ID size"
-msgstr "Правильный размер Tox ID"
-
-#: ui/ContactListWindow.vala:461
-#, c-format
-msgid "Venom (%s)"
-msgstr "Venom (%s)"
-
-#: ui/ConversationTextView.vala:139
-#, c-format
-msgid "[%s] "
-msgstr "[%s] "
-
-#: ui/ContactListWindow.vala:638
-#, c-format
-msgid "[ac] %i:%s\n"
-msgstr "[ac] %i:%s\n"
-
-#: ui/ContactListWindow.vala:598
-#, c-format
-msgid "[fr] %s:%s\n"
-msgstr "[fr] %s:%s\n"
-
-#: ui/ContactListWindow.vala:763
-#, c-format
-msgid "[ga] %s [%i]@%i: %s\n"
-msgstr "[ga] %s [%i]@%i: %s\n"
-
-#: ui/ContactListWindow.vala:734
-#, c-format
-msgid "[gm] %s [%i]@%i: %s\n"
-msgstr "[gm] %s [%i]@%i: %s\n"
-
-#: ui/ContactListWindow.vala:660
-#, c-format
-msgid "[rr] %s:%u\n"
-msgstr "[rr] %s:%u\n"
-
-#: ui/ContactListWindow.vala:656
-#, c-format
-msgid "[us] %s:%i\n"
-msgstr "[us] %s:%i\n"
-
-#: ui/contact_list.ui:96
-msgid "_Away"
-msgstr "_Отошел"
-
-#: ui/user_info_window.ui:254
-msgid "_Browse..."
-msgstr "_Обзор..."
-
-#: ui/contact_list.ui:107
-msgid "_Busy"
-msgstr "_Занят"
-
-#: ui/contact_list.ui:61
-msgid "_Copy ID to clipboard"
-msgstr "_Скопировать Tox ID в буфер обмена"
-
-#: ui/contact_list.ui:50
-msgid "_Edit user"
-msgstr "_Редактировать пользователя"
-
-#: ui/add_contact_dialog.ui:94
-msgid "_Message (optional):"
-msgstr "_Статус (необязательный):"
-
-#: ui/add_contact_dialog.ui:54
-msgid "_Nickname (optional):"
-msgstr "_Ник (необязательный):"
-
-#: ui/contact_list.ui:85
-msgid "_Online"
-msgstr "_В сети"
-
-#: ui/add_contact_dialog.ui:27
-msgid "_Tox ID:"
-msgstr "_Tox ID:"
-
-#: ui/contact_list.ui:278
-msgid "connecting..."
-msgstr "подключение..."
-
-#: ui/settings_window.ui:160
-msgid "days"
-msgstr "дни"
+#: src/ui/user_info_widget.ui:87
+msgid "Take a picture"
+msgstr ""
+
+#: src/ui/user_info_widget.ui:109
+msgid "Choose a file"
+msgstr ""
+
+#: src/ui/conference_window.ui:179
+msgid "No one here..."
+msgstr ""
+
+#: src/ui/conference_window.ui:280
+msgid "Show peers"
+msgstr ""
+
+#: src/undo/TextBufferUndoBinding.vala:169
+msgid "_Redo"
+msgstr ""
+
+#: src/undo/TextBufferUndoBinding.vala:174
+msgid "_Undo"
+msgstr ""
+
+#: src/viewmodel/FriendInfoViewModel.vala:65
+msgid "Online right now"
+msgstr ""
+
+#: src/viewmodel/FriendInfoViewModel.vala:67
+msgid "Never seen online"
+msgstr ""
+
+#: src/viewmodel/FriendInfoViewModel.vala:69
+msgid "Last seen: %s"
+msgstr ""
+
+#: src/view/ConversationWindow.vala:120
+msgid "%s is typing…"
+msgstr ""
+
+#: src/ui/conversation_window.ui:155
+msgid "Attach screenshot…"
+msgstr ""
+
+#: src/ui/conversation_window.ui:180
+msgid "Attach file…"
+msgstr ""
+
+#: src/view/AboutDialog.vala:54 data/chat.tox.venom.desktop.in:4
+msgid "A modern Tox client for the Linux desktop"
+msgstr ""
+
+#: src/view/AboutDialog.vala:55
+msgid "Copyright © 2013-2018 Venom authors and contributors"
+msgstr ""
+
+#: data/chat.tox.venom.desktop.in:3
+msgid "Venom"
+msgstr ""
+
+#: data/chat.tox.venom.desktop.in:5
+msgid "tox;instant messaging;video chat;"
+msgstr ""
+
+#: data/chat.tox.venom.desktop.in:7
+msgid "chat.tox.venom-symbolic"
+msgstr ""
-#: ui/settings_window.ui:127
-msgid "delete after"
-msgstr "удалить после"
-
-#: Main.vala:49
-#, c-format
-msgid "error: %s\n"
-msgstr "ошибка: %s\n"
-
-#: ui/ContactListWindow.vala:668
-msgid "established"
-msgstr "создан"
-
-#: ui/ContactListWindow.vala:569
-#, c-format
-msgid "failed to send file %s to %s"
-msgstr "произошла ошибка при отправке файла от %s к %s"
-
-#: ui/ContactListWindow.vala:1077
-#, c-format
-msgid "groupchat #%i"
-msgstr "групповой чат #%i"
-
-#: ui/settings_window.ui:104
-msgid "indefinitely"
-msgstr "неопределенный срок"
-
-#: ui/ContactListWindow.vala:668
-msgid "lost"
-msgstr "потерянный"
-
-#: core/GroupChat.vala:56
-msgid "no one connected"
-msgstr "никто не подключен"
-
-#: ui/ContactListWindow.vala:663
-msgid "offline"
-msgstr "не в сети"
-
-#: ui/ContactListWindow.vala:663
-msgid "online"
-msgstr "в сети"
-
-#: ui/ContactListWindow.vala:798
-#, c-format
-msgid "received file send request friend: %i filenumber: %i filename: %s \n"
-msgstr "получен запрос от %i на передачу %i файлов %s \n"
-
-#: ui/ContactListWindow.vala:562
-#, c-format
-msgid "sending file %s to %s\n"
-msgstr "отправка файла %s к %s\n"
-
-#: ui/ContactListWindow.vala:1129
-#, c-format
-msgid "setting alias: %s\n"
-msgstr "установка алиаса: %s\n"
-
-#: core/ToxDns.vala:95
-#, c-format
-msgid "tox 1 ID found: %s\n"
-msgstr "Tox IDv1 найден: %s\n"
-
-#: core/ToxDns.vala:100
-#, c-format
-msgid "tox 2 ID found: %s %s\n"
-msgstr "Tox IDv2 найден: %s %s\n"
-
-#: ui/AboutDialog.vala:46
-msgid "translator-credits"
-msgstr "Ackermann Yuriy"
diff --git a/po/zh_CN.po b/po/zh_CN.po
index d40a474..182792d 100644
--- a/po/zh_CN.po
+++ b/po/zh_CN.po
@@ -8,7 +8,7 @@ msgid ""
msgstr ""
"Project-Id-Version: Venom \n"
"Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2014-06-17 21:05+0200\n"
+"POT-Creation-Date: 2018-02-19 16:47+0100\n"
"PO-Revision-Date: 2014-08-27 13:00+0800\n"
"Last-Translator: kaiman \n"
"Language-Team: Chinese (simplified) \n"
@@ -17,999 +17,572 @@ msgstr ""
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
-#: core/ToxSession.vala:725
-#, c-format
-msgid " %s\n"
-msgstr ""
-
-#: core/DhtNode.vala:47
-msgid " (ipv6)"
-msgstr ""
-
-#: ui/ContactListWindow.vala:627
-#, c-format
-msgid "%F"
-msgstr ""
-
-#: core/Message.vala:47
-msgid "%R:%S"
-msgstr ""
-
-#: core/GroupChat.vala:52
-#, c-format
-msgid "%i people connected"
-msgstr "%i 人在线"
-
-#: core/GroupChat.vala:54
-#, c-format
-msgid "%i person connected"
-msgstr "%i 人在线"
-
-#: core/Contact.vala:69 core/Contact.vala:83
-#, c-format
-msgid "%s (%s)"
+#: src/Main.vala:29
+msgid "Set level of messages to log"
msgstr ""
-#: ui/ContactListWindow.vala:648
-#, c-format
-msgid "%s changed his name to %s\n"
+#: src/Main.vala:29
+msgid ""
msgstr ""
-#: ui/ContactListWindow.vala:652
-#, c-format
-msgid "%s changed his status to %s\n"
-msgstr "%s 切换他的状态到 %s\n"
-
-#: ui/ContactListWindow.vala:663
-#, c-format
-msgid "%s is now %s.\n"
-msgstr "%s 现在 %s。\n"
-
-#: ui/ConversationWidget.vala:60
-#, c-format
-msgid "%s is typing..."
-msgstr "%s 正在输入......"
-
-#: ui/ContactListWindow.vala:131
-#, c-format
-msgid "%s: %s\n"
+#: src/Main.vala:30
+msgid "Display version number"
msgstr ""
-#: core/DhtNode.vala:47
+#: src/Main.vala:65
#, c-format
-msgid "%s:%u%s %s"
+msgid "error: %s\n"
msgstr ""
-#: ui/ContactListWindow.vala:714
-#, c-format
-msgid "'%s' has invited you to a groupchat, do you want to accept?"
-msgstr "'%s' 邀请你加入一个群聊,你愿意接受吗?"
-
-#: ui/ContactListWindow.vala:577
+#: src/Main.vala:66
#, c-format
-msgid "* %s"
+msgid "Run '%s --help' to see a full list of available command line options.\n"
msgstr ""
-#: ui/ContactListWindow.vala:627
+#: src/core/NotificationListener.vala:51
#, c-format
-msgid "<%i>"
+msgid "New message from %s"
msgstr ""
-#: ui/ContactListWindow.vala:627
-#, c-format
-msgid "<%s> %s:%s\n"
+#: src/core/R.vala:70
+msgid "Tox User"
msgstr ""
-#: ui/ConversationWidget.vala:51 ui/GroupConversationWidget.vala:47
+#: src/tox/GroupchatContact.vala:45
#, c-format
-msgid "%s"
-msgstr ""
-
-#: ui/user_info_window.ui:119
-msgid "Tox"
+msgid "%u Peers online"
msgstr ""
-#: ui/user_info_window.ui:282
-msgid "User"
-msgstr "用户"
-
-#: core/Contact.vala:72 core/Contact.vala:86 ui/ConversationView.vala:55
-#, c-format
-msgid "%s"
+#: src/ui/AboutDialog.vala:53
+msgid "Packagers"
msgstr ""
-#: core/Message.vala:152 core/Message.vala:191
-msgid ""
-msgstr "<未知>"
-
-#: ui/AddContactDialog.vala:76
-msgid "Add contact"
-msgstr "添加联系人"
-
-#: ui/ContactListWindow.vala:617
-#, c-format
-msgid "Added new friend #%i\n"
-msgstr "添加新好友 #%i\n"
-
-#: ui/ContactListWindow.vala:1125 ui/ContactListWindow.vala:1137
-msgid "Adding Friend failed"
-msgstr "添加好友失败"
-
-#: ui/ContactListWindow.vala:210
-msgid "All"
-msgstr "全部"
-
-#: ui/ContactListWindow.vala:1060 ui/ContactListWindow.vala:1082
-#, c-format
-msgid "Are you sure you want to delete '%s' from your contact list?"
-msgstr "确实要从您的联系人名单中删除 '%s'?"
-
-#: core/ToxSession.vala:33
-msgid "Away"
-msgstr "离开"
-
-#: core/ToxSession.vala:717
-#, c-format
-msgid "Background thread started.\n"
-msgstr "后台线程启动。\n"
-
-#: core/ToxSession.vala:756
-#, c-format
-msgid "Background thread stopped.\n"
-msgstr "后台线程停止。\n"
-
-#: core/Tools.vala:142
-msgid "Bad checksum"
-msgstr "校验和错误"
-
-#: core/ToxSession.vala:35
-msgid "Busy"
-msgstr "忙"
-
-#: ui/conversation_window.ui:156
-msgid "Call contact"
-msgstr "呼叫联系人"
-
-#: ui/conversation_window.ui:174
-msgid "Call contact with video"
-msgstr "呼叫一个视频通话"
-
-#: core/Tools.vala:158 core/Tools.vala:171
-#, c-format
-msgid "Can't create action regex: %s.\n"
-msgstr "无法创建动作的正则表达式: %s。\n"
-
-#: core/SqliteTools.vala:75
-#, c-format
-msgid "Can't open database: %d: %s\n"
-msgstr "无法打开数据库: %d: %s\n"
-
-#: core/Tools.vala:136
-msgid "Can't send to own key"
-msgstr "不能发送自己的密匙"
-
-#: ui/FileTransferChatEntry.vala:119
-msgid "Canceled"
-msgstr "取消"
-
-#: ui/contact_list.ui:72
-msgid "Change _Status"
-msgstr "改变状态(_S)"
-
-#: ui/ContactListWindow.vala:670
-msgid "Connected to the network"
-msgstr "连接到网络"
-
-#: core/ToxSession.vala:720
-#, c-format
-msgid "Connecting to DHT Nodes:\n"
-msgstr "连接到DHT节点:\n"
-
-#: ui/ContactListWindow.vala:668
-#, c-format
-msgid "Connection to DHT %s.\n"
-msgstr "连接到DHT %s。\n"
-
-#: ui/ContactListWindow.vala:907
-#, c-format
-msgid "Contact accepted file sending request\n"
-msgstr "联系人接受文件发送请求\n"
-
-#: ui/ContactListWindow.vala:508
-#, c-format
-msgid "Copied Tox ID to clipboard\n"
-msgstr "复制 TOX ID 到剪贴板\n"
-
-#: ui/ContactListWindow.vala:1135
-#, c-format
-msgid "Could not add friend: %s.\n"
-msgstr "不能添加好友: %s。\n"
-
-#: ui/ContactListWindow.vala:1123
-msgid "Could not add friend: Invalid ID\n"
-msgstr "不能添加好友: 无效的ID\n"
-
-#: core/SqliteTools.vala:40
-#, c-format
-msgid "Could not bind int to %s."
-msgstr "无法绑定 int 到 %s 。"
-
-#: core/SqliteTools.vala:50
-#, c-format
-msgid "Could not bind int64 to %s."
-msgstr "无法绑定 int64 到 %s 。"
-
-#: core/SqliteTools.vala:60
-#, c-format
-msgid "Could not bind text to %s"
-msgstr "无法绑定 text 到 %s 。"
-
-#: ui/ContactListWindow.vala:447
-#, c-format
-msgid "Could not change user name!\n"
-msgstr "无法更改用户名称!\n"
-
-#: ui/ContactListWindow.vala:455
-#, c-format
-msgid "Could not change user statusmessage!\n"
-msgstr "无法更改用户状态消息!\n"
-
-#: ui/ContactListWindow.vala:1189
-#, c-format
-msgid "Could not create a new groupchat.\n"
-msgstr "不能创建一个新群聊。\n"
-
-#: ui/ContactListWindow.vala:725
-#, c-format
-msgid "Could not join groupchat.\n"
-msgstr "不能加入群聊。\n"
-
-#: ui/ContactListWindow.vala:146
-#, c-format
-msgid "Could not load session data (%s), creating new one.\n"
-msgstr "无法加载会话数据(%s),创建一个新的。\n"
-
-#: ui/ContactListWindow.vala:130
-#, c-format
-msgid "Could not read theme from \"%s\""
-msgstr "无法从\"%s\"读取主题"
-
-#: ui/ContactListWindow.vala:1090
-#, c-format
-msgid "Could not remove %s.\n"
-msgstr "无法删除 %s.\n"
-
-#: ui/ContactListWindow.vala:1068
-#, c-format
-msgid "Could not remove contact %i.\n"
-msgstr "无法删除联系人 %i。\n"
-
-#: core/ToxSession.vala:352
-#, c-format
-msgid "Could not remove peer [%i] from groupchat #%i (no such peer)\n"
-msgstr "无法删除对端 [%i] 从群聊 #%i (无此对端)\n"
-
-#: ui/ContactListWindow.vala:1112
-msgid "Could not resolve ID from DNS record\n"
-msgstr "无法从DNS记录中解析 ID\n"
-
-#: ui/contact_list.ui:416
-msgid "Create groupchat"
-msgstr "创建群聊"
-
-#: ui/settings_window.ui:301
-msgid "Default Tox DNS ID suffix:"
-msgstr "缺省 Tox DNS ID 后缀:"
-
-#: ui/FileTransferChatEntry.vala:125 ui/FileTransferChatEntry.vala:129
-msgid "Disconnected"
+#: src/ui/AboutDialog.vala:58
+msgid "translator-credits"
msgstr ""
-#: ui/ContactListWindow.vala:673
-msgid "Disconnected from the network"
+#: src/ui/AboutDialog.vala:61
+msgid "Visit us on Github"
msgstr ""
-#: ui/UserInfoWindow.vala:86
-msgid "Edit user information"
+#: src/ui/add_contact_widget.ui:6
+msgid "Please let me add you to my contact list. 😁"
msgstr ""
-#: ui/ContactListWindow.vala:899
-#, c-format
-msgid "Ended file transfer for %s to %s\n"
+#: src/ui/add_contact_widget.ui:38
+msgid "Send a friend request"
msgstr ""
-#: ui/ContactListWindow.vala:102
-#, c-format
-msgid "Ending session...\n"
+#: src/ui/add_contact_widget.ui:72
+msgid "_ID:"
msgstr ""
-#: ui/add_contact_dialog.ui:40
-msgid "Enter a Tox ID here or a Tox URI"
+#: src/ui/add_contact_widget.ui:89
+msgid "Enter a Tox ID or URI here"
msgstr ""
-#: core/ContactStorage.vala:108
-#, c-format
-msgid "Error creating contacts insert statement: %d: %s\n"
-msgstr ""
+#: src/ui/add_contact_widget.ui:93 src/ui/create_groupchat_widget.ui:89
+#, fuzzy
+msgid "paste from clipboard"
+msgstr "复制ID到剪贴板(_C)"
-#: core/ContactStorage.vala:113
-#, c-format
-msgid "Error creating contacts select statement: %d: %s\n"
+#: src/ui/add_contact_widget.ui:105
+msgid "Enter your friends Tox ID"
msgstr ""
-#: core/ContactStorage.vala:103
-#, c-format
-msgid "Error creating contacts table: %s\n"
-msgstr ""
+#: src/ui/add_contact_widget.ui:137
+#, fuzzy
+msgid "_Message:"
+msgstr "状态消息:"
-#: core/DhtNodeStorage.vala:177
-#, c-format
-msgid "Error creating dht nodes insert statement: %d: %s\n"
+#: src/ui/add_contact_widget.ui:163
+msgid "Send a custom message to be displayed to the friend you are adding"
msgstr ""
-#: core/DhtNodeStorage.vala:182
-#, c-format
-msgid "Error creating dht nodes select statement: %d: %s\n"
-msgstr ""
+#: src/ui/add_contact_widget.ui:185
+#, fuzzy
+msgid "Send your friend a short message"
+msgstr "当我正在输入时其他人可以看到这一状态"
-#: core/DhtNodeStorage.vala:172
-#, c-format
-msgid "Error creating dht nodes table: %s\n"
+#: src/ui/add_contact_widget.ui:215
+msgid "Send"
msgstr ""
-#: core/ToxDns.vala:36
-#, c-format
-msgid "Error creating tox dns regex: %s\n"
-msgstr ""
+#: src/ui/app_menu.ui:7
+#, fuzzy
+msgid "_Preferences"
+msgstr "打开首选项"
-#: core/ToxDns.vala:51
-#, c-format
-msgid "Error creating tox uri regex: %s\n"
+#: src/ui/app_menu.ui:13
+msgid "About"
msgstr ""
-#: ui/ConversationTextView.vala:184
-#, c-format
-msgid "Error matching uri regex: %s\n"
+#: src/ui/app_menu.ui:17
+msgid "_Quit"
msgstr ""
-#: ui/ConversationWidget.vala:308
-#, c-format
-msgid "Error occured while getting file size: %s"
-msgstr ""
+#: src/ui/conference_info_widget.ui:39
+#, fuzzy
+msgid "Conference"
+msgstr "打开首选项"
-#: core/ToxSession.vala:111
-#, c-format
-msgid "Error opening database: %s\n"
-msgstr ""
+#: src/ui/conference_info_widget.ui:56
+#, fuzzy
+msgid "Leave Groupchat"
+msgstr "创建群聊"
-#: core/Settings.vala:112
-#, c-format
-msgid "Error reading configs:%s\n"
+#: src/ui/conference_info_widget.ui:105
+msgid "Title:"
msgstr ""
-#: core/ToxDns.vala:81
-#, c-format
-msgid "Error resolving name: %s\n"
+#: src/ui/conference_info_widget.ui:145 src/ui/friend_info_widget.ui:449
+#: src/ui/user_info_widget.ui:401
+msgid "Apply"
msgstr ""
-#: core/MessageLog.vala:135
-#, c-format
-msgid "Error retrieving logs from sqlite database: %s\n"
+#: src/ui/conference_info_widget.ui:163
+msgid "Peers"
msgstr ""
-#: core/Settings.vala:99
-#, c-format
-msgid "Error saving configs:%s\n"
-msgstr ""
+#: src/ui/conference_window.ui:206 src/ui/conversation_window.ui:262
+#: src/ui/user_info_widget.ui:139 src/ui/user_info_widget.ui:140
+#, fuzzy
+msgid "Insert Emoji"
+msgstr "插入表情符"
-#: core/Tools.vala:123
-#, c-format
-msgid "Error when doing uri markup: %s"
+#: src/ui/contact_list_widget.ui:136
+msgid "Filter contacts by status"
msgstr ""
-#: ui/ConversationTextView.vala:245
-#, c-format
-msgid "Error when showing uri: %s\n"
-msgstr ""
+#: src/ui/contact_list_widget.ui:142
+msgid "All"
+msgstr "全部"
-#: ui/ContactListWindow.vala:168
-#, c-format
-msgid "Error while loading icon: %s\n"
-msgstr ""
+#: src/ui/contact_list_widget.ui:249
+#, fuzzy
+msgid "Add a contact"
+msgstr "添加联系人"
-#: core/ResourceFactory.vala:126
-#, c-format
-msgid "Error while loading image from \"%s\":%s\n"
-msgstr ""
+#: src/ui/contact_list_widget.ui:270 src/ui/create_groupchat_widget.ui:35
+#, fuzzy
+msgid "Create a groupchat"
+msgstr "创建群聊"
-#: core/ToxSession.vala:801
-msgid "Error while loading messenger data."
+#: src/ui/contact_list_widget.ui:291
+msgid "View file transfers"
msgstr ""
-#: core/ToxSession.vala:795
-msgid "Error while reading from stream."
-msgstr ""
+#: src/ui/contact_list_widget.ui:312
+msgid "Open preferences"
+msgstr "打开首选项"
-#: ui/FileTransferChatEntry.vala:171
-#, c-format
-msgid "Error while trying to create file: %s\n"
+#: src/ui/conversation_window.ui:103
+msgid "Start a call"
msgstr ""
-#: ui/ContactListWindow.vala:961
-#, c-format
-msgid "Error while trying to write data to file\n"
+#: src/ui/conversation_window.ui:128
+msgid "Start a videocall"
msgstr ""
-#: core/ToxSession.vala:828
-msgid "Error while writing to stream."
-msgstr ""
+#: src/ui/conversation_window.ui:284
+#, fuzzy
+msgid "Insert attachment"
+msgstr "插入表情符"
-#: core/ContactStorage.vala:88
-#, c-format
-msgid "Error writing contact to sqlite database: %s\n"
+#: src/ui/create_groupchat_widget.ui:69
+msgid "_Title:"
msgstr ""
-#: core/MessageLog.vala:118
-#, c-format
-msgid "Error writing message to sqlite database: %s\n"
-msgstr ""
+#: src/ui/create_groupchat_widget.ui:88
+#, fuzzy
+msgid "Groupchat"
+msgstr "创建群聊"
-#: core/MessageLog.vala:186 core/MessageLog.vala:193
-#, c-format
-msgid "Error: %d: %s\n"
+#: src/ui/create_groupchat_widget.ui:101
+msgid "Name the groupchat (optional)"
msgstr ""
-#: core/MessageLog.vala:169 core/MessageLog.vala:179
-#: ui/ConversationView.vala:78
-#, c-format
-msgid "Error: %s\n"
+#: src/ui/create_groupchat_widget.ui:133
+msgid "T_ype:"
msgstr ""
-#: core/ToxSession.vala:788
-#, c-format
-msgid "File \"%d\" does not exist."
+#: src/ui/create_groupchat_widget.ui:153
+msgid "text"
msgstr ""
-#: ui/ContactListWindow.vala:929
-#, c-format
-msgid "File transfer finished for file number %u"
+#: src/ui/create_groupchat_widget.ui:168
+msgid "video"
msgstr ""
-#: ui/ContactListWindow.vala:925
-#, c-format
-msgid "File transfer was rejected for file number %u"
+#: src/ui/create_groupchat_widget.ui:195
+msgid "Select a groupchat type"
msgstr ""
-#: ui/FileTransferChatEntry.vala:94
-msgid "File was rejected"
+#: src/ui/create_groupchat_widget.ui:224
+msgid "Create"
msgstr ""
-#: ui/settings_window.ui:236
-msgid "Flash window when a new message arrives"
-msgstr "一条新消息到达时闪频振动"
-
-#: ui/ContactListWindow.vala:614
-#, c-format
-msgid "Friend could not be added.\n"
+#: src/ui/downloads_widget.ui:35
+msgid "File transfers"
msgstr ""
-#: core/Tools.vala:138
-msgid "Friend request already sent"
-msgstr ""
+#: src/ui/friend_info_widget.ui:45
+#, fuzzy
+msgid "Friend profile"
+msgstr "发送文件"
-#: core/Tools.vala:148
-msgid "Friend request successfully sent"
+#: src/ui/friend_info_widget.ui:62
+msgid "Remove from your friends list"
msgstr ""
-#: ui/ContactListWindow.vala:1142
-#, c-format
-msgid "Friend request successfully sent. Friend added as %i.\n"
+#: src/ui/friend_info_widget.ui:111 src/ui/user_info_widget.ui:75
+msgid "Username:"
msgstr ""
-#: ui/ContactListWindow.vala:771
-#, c-format
-msgid "Group action from unknown contact #%i [%i]\n"
-msgstr ""
-
-#: ui/ContactListWindow.vala:708
-#, c-format
-msgid "Group invite from %s with public key %s\n"
-msgstr ""
+#: src/ui/friend_info_widget.ui:155 src/ui/user_info_widget.ui:120
+#, fuzzy
+msgid "Statusmessage:"
+msgstr "状态消息:"
-#: ui/ContactListWindow.vala:742
-#, c-format
-msgid "Group message from unknown contact #%i [%i]\n"
+#: src/ui/friend_info_widget.ui:200 src/ui/user_info_widget.ui:168
+msgid "Image:"
msgstr ""
-#: core/GroupChat.vala:45
-#, c-format
-msgid "Groupchat #%i"
+#: src/ui/friend_info_widget.ui:245
+msgid "Last seen:"
msgstr ""
-#: ui/ContactListWindow.vala:896
-#, c-format
-msgid "I/O error while trying to close file stream: %s\n"
+#: src/ui/friend_info_widget.ui:290
+msgid "Alias:"
msgstr ""
-#: ui/ContactListWindow.vala:888
-#, c-format
-msgid "I/O error while trying to read file: %s\n"
+#: src/ui/friend_info_widget.ui:318
+msgid "Set a custom alias to quickly find your friends"
msgstr ""
-#: ui/AddContactDialog.vala:96
-msgid "ID contains invalid characters"
+#: src/ui/friend_info_widget.ui:362 src/ui/user_info_widget.ui:251
+msgid "Tox"
msgstr ""
-#: ui/user_info_window.ui:40
+#: src/ui/friend_info_widget.ui:395 src/ui/user_info_widget.ui:290
msgid "ID:"
msgstr ""
-#: ui/ContactListWindow.vala:86
-#, c-format
-msgid "ID: %s\n"
+#: src/ui/message_widget.ui:88
+msgid "Message sent ✓"
msgstr ""
-#: ui/user_info_window.ui:222
-msgid "Icon:"
-msgstr "头像"
-
-#: core/SqliteTools.vala:37 core/SqliteTools.vala:47 core/SqliteTools.vala:57
-#, c-format
-msgid "Index for %s not found."
+#: src/ui/message_widget.ui:104
+msgid "Message received ✓"
msgstr ""
-#: ui/conversation_window.ui:290
-msgid "Insert Smiley"
-msgstr "插入表情符"
-
-#: core/ToxDns.vala:113
-#, c-format
-msgid "Invalid record\n"
+#: src/ui/peer_entry.ui:55
+msgid "This peer is also in your friends list"
msgstr ""
-#: core/ToxDns.vala:64
-#, c-format
-msgid "Invalid tox uri\n"
-msgstr ""
-
-#: ui/ContactListWindow.vala:728
-#, c-format
-msgid "Joined Groupchat #%i\n"
+#: src/ui/settings_widget.ui:41
+msgid "KiB/MiB"
msgstr ""
-#: ui/settings_window.ui:18
+#: src/ui/settings_widget.ui:45
msgid "KB/MB"
msgstr ""
-#: ui/settings_window.ui:78
-msgid "Keep history"
-msgstr "保持历史"
-
-#: ui/settings_window.ui:14
-msgid "KiB/MiB"
+#: src/ui/settings_widget.ui:95
+msgid "General"
msgstr ""
-#: core/Contact.vala:117
-#, c-format
-msgid "Last seen: %s"
-msgstr ""
-
-#: ui/AddContactDialog.vala:53
-#, c-format
-msgid "Loading add contact window failed!\n"
-msgstr ""
+#: src/ui/settings_widget.ui:138
+#, fuzzy
+msgid "Connection"
+msgstr "连接中......"
-#: ui/ConversationWidget.vala:71 ui/SettingsWindow.vala:32
-#, c-format
-msgid "Loading conversation window failed!\n"
+#: src/ui/settings_widget.ui:225
+msgid "Appearance"
msgstr ""
-#: ui/FileTransferChatEntry.vala:40
-#, c-format
-msgid "Loading message widget failed!\n"
+#: src/ui/settings_widget.ui:270
+msgid "Dark Theme"
msgstr ""
-#: core/Tools.vala:132
-msgid "Message too long"
+#: src/ui/settings_widget.ui:283
+msgid "Whether Venom should use a dark theme"
msgstr ""
-#: ui/settings_window.ui:337
-msgid "Miscellaneous"
-msgstr "杂项"
-
-#: ui/user_info_window.ui:192
-msgid "Name:"
-msgstr "名字"
-
-#: ui/ContactListWindow.vala:604
-#, c-format
-msgid ""
-"New friend request from '%s'.\n"
-"Do you want to accept?"
+#: src/ui/settings_widget.ui:340
+msgid "Show notifications"
msgstr ""
-#: ui/AddContactDialog.vala:90
-msgid "No ID given"
+#: src/ui/settings_widget.ui:353
+msgid "Show a notification for new messages"
msgstr ""
-#: core/Tools.vala:134
-msgid "No message included"
+#: src/ui/settings_widget.ui:410
+msgid "Minimize to tray"
msgstr ""
-#: core/ToxDns.vala:103
-#, c-format
-msgid "No pin privided, aborting...\n"
+#: src/ui/settings_widget.ui:423
+msgid "Minimize app to system tray"
msgstr ""
-#: ui/contact_list.ui:118
-msgid "O_ffline"
-msgstr "离线(_F)"
-
-#: core/Contact.vala:98 core/Contact.vala:108 core/ToxSession.vala:37
-msgid "Offline"
-msgstr "离线"
-
-#: core/GroupChatContact.vala:32 core/ToxSession.vala:31
-#: ui/ContactListWindow.vala:208
-msgid "Online"
-msgstr "在线"
-
-#: ui/contact_list.ui:449
-msgid "Open preferences"
-msgstr "打开首选项"
-
-#: core/Tools.vala:146
-msgid "Out of memory"
-msgstr "内存溢出"
-
-#: ui/FileTransferChatEntry.vala:104
-msgid "Paused"
-msgstr "暂停"
+#: src/ui/settings_widget.ui:506
+msgid "Privacy"
+msgstr "隐私"
-#: ui/PinDialog.vala:37
-#, c-format
-msgid ""
-"Please insert PIN for \n"
-"%s"
+#: src/ui/settings_widget.ui:550
+msgid "Send typing notifications"
msgstr ""
-#: ui/PinDialog.vala:49
-msgid "Please insert PIN..."
-msgstr ""
+#: src/ui/settings_widget.ui:563
+#, fuzzy
+msgid "Show others when I am typing"
+msgstr "当我正在输入时其他人可以看到这一状态"
-#: ui/add_contact_dialog.ui:6
-msgid "Please let me add you to my contact list."
-msgstr ""
+#: src/ui/settings_widget.ui:646
+#, fuzzy
+msgid "History"
+msgstr "保持历史"
-#: ui/settings_window.ui:221
-msgid "Privacy"
-msgstr "隐私"
+#: src/ui/settings_widget.ui:694
+#, fuzzy
+msgid "Keep indefinitely"
+msgstr "无限制"
-#: ui/ContactListWindow.vala:869
-#, c-format
-msgid "Read incorrect number of bytes from file\n"
-msgstr ""
+#: src/ui/settings_widget.ui:714
+msgid "delete after"
+msgstr "删除早于"
-#: ui/FileTransferChatEntry.vala:113
-msgid "Receiving failed"
-msgstr ""
+#: src/ui/settings_widget.ui:731
+msgid "days"
+msgstr "天记录"
-#: ui/ContactListWindow.vala:1114
-msgid "Resolving ID failed"
+#: src/ui/settings_widget.ui:785
+msgid "Delete all previous conversations"
msgstr ""
-#: ui/ContactListWindow.vala:427
-#, c-format
-msgid "Retrieved contact %s from savefile.\n"
+#: src/ui/settings_widget.ui:844
+msgid "Update bootstrap nodes"
msgstr ""
-#: Main.vala:50
-#, c-format
-msgid "Run '%s --help' to see a full list of available command line options.\n"
+#: src/ui/settings_widget.ui:880
+msgid "Tox bootstrap nodes"
msgstr ""
-#: core/MessageLog.vala:86
-#, c-format
-msgid "SQLite database closed.\n"
+#: src/ui/user_info_widget.ui:41
+msgid "User profile"
msgstr ""
-#: core/MessageLog.vala:82
-#, c-format
-msgid "SQLite database created.\n"
-msgstr ""
+#: src/ui/user_info_widget.ui:332
+#, fuzzy
+msgid "Copy to clipboard"
+msgstr "复制ID到剪贴板(_C)"
-#: ui/FileTransferChatEntry.vala:158
-msgid "Save"
+#: src/ui/welcome_widget.ui:39
+msgid "A new kind of instant messaging"
msgstr ""
-#: ui/FileTransferChatEntry.vala:155
-msgid "Save file"
+#: src/ui/welcome_widget.ui:52
+msgid "Chat with your friends and family without anyone else listening in."
msgstr ""
-#: ui/ContactListWindow.vala:120
-#, c-format
-msgid "Saving session file failed: %s\n"
+#: src/ui/welcome_widget.ui:100
+msgid "Learn more"
msgstr ""
-#: ui/FileTransferChatEntry.vala:165
-#, c-format
-msgid "Saving to: %s\n"
-msgstr ""
+#, fuzzy
+#~ msgid "contact_name"
+#~ msgstr "添加联系人"
-#: ui/ContactListWindow.vala:116
-#, c-format
-msgid "Saving tox session data\n"
-msgstr ""
+#~ msgid "Online"
+#~ msgstr "在线"
-#: ui/ConversationWidget.vala:282
-msgid "Select"
-msgstr ""
+#~ msgid "Could not bind int to %s."
+#~ msgstr "无法绑定 int 到 %s 。"
-#: ui/ConversationWidget.vala:279
-msgid "Select a file to send"
-msgstr ""
+#~ msgid "Could not bind int64 to %s."
+#~ msgstr "无法绑定 int64 到 %s 。"
-#: ui/add_contact_dialog.ui:113
-msgid "Send a custom message to be displayed to the friend you are adding"
-msgstr ""
+#~ msgid "Could not bind text to %s"
+#~ msgstr "无法绑定 text 到 %s 。"
-#: ui/conversation_window.ui:308
-msgid "Send file"
-msgstr "发送文件"
+#~ msgid "Can't open database: %d: %s\n"
+#~ msgstr "无法打开数据库: %d: %s\n"
-#: ui/conversation_window.ui:341
-msgid "Send message"
-msgstr "发送消息"
+#~ msgid ""
+#~ msgstr "<未知>"
-#: ui/FileTransferChatEntry.vala:107
-msgid "Sending failed"
-msgstr ""
+#~ msgid "%i people connected"
+#~ msgstr "%i 人在线"
-#: ui/ContactListWindow.vala:111
-#, c-format
-msgid "Session ended gracefully.\n"
-msgstr ""
+#~ msgid "%i person connected"
+#~ msgstr "%i 人在线"
-#: ui/add_contact_dialog.ui:67
-msgid "Set a custom nickname for the friend you are about to add"
-msgstr ""
+#~ msgid "Offline"
+#~ msgstr "离线"
-#: core/Tools.vala:144
-msgid "Set new nospam"
-msgstr ""
+#~ msgid "Away"
+#~ msgstr "离开"
-#: ui/settings_window.ui:30
-msgid "Settings"
-msgstr "设置"
+#~ msgid "Busy"
+#~ msgstr "忙"
-#: core/Settings.vala:102
-#, c-format
-msgid "Settings saved.\n"
-msgstr ""
+#, fuzzy
+#~ msgid "_Invite to new groupchat"
+#~ msgstr "创建群聊"
-#: ui/settings_window.ui:186
-msgid "Show _others when I am typing"
-msgstr "当我正在输入时其他人可以看到这一状态"
+#, fuzzy
+#~ msgid "Could not export data file: "
+#~ msgstr "不能添加好友: %s。\n"
-#: ui/settings_window.ui:258
-msgid "Show filesize in"
-msgstr "显示文件尺寸用"
+#~ msgid "Could not read theme from \"%s\""
+#~ msgstr "无法从\"%s\"读取主题"
-#: ui/settings_window.ui:202
-msgid "Show me when others are typing"
-msgstr "当其他人正在输入时我可以看到这一状态"
+#~ msgid "Connected to the network"
+#~ msgstr "连接到网络"
-#: Main.vala:70
-#, c-format
-msgid "Starting in offline mode\n"
-msgstr ""
+#~ msgid "'%s' has invited you to a groupchat, do you want to accept?"
+#~ msgstr "'%s' 邀请你加入一个群聊,你愿意接受吗?"
-#: ui/user_info_window.ui:178
-msgid "Status message:"
-msgstr "状态消息:"
+#~ msgid "Are you sure you want to delete '%s' from your contact list?"
+#~ msgstr "确实要从您的联系人名单中删除 '%s'?"
-#: ui/ContactListWindow.vala:408
-#, c-format
-msgid "Theme refreshed\n"
-msgstr ""
+#~ msgid "Could not resolve ID from DNS record\n"
+#~ msgstr "无法从DNS记录中解析 ID\n"
-#: ui/Client.vala:116
-msgid "There is currently no help available"
-msgstr ""
+#~ msgid "Adding Friend failed"
+#~ msgstr "添加好友失败"
-#: core/ResourceFactory.vala:77
-msgid "Tox User"
-msgstr ""
+#~ msgid "Could not add friend: Invalid ID\n"
+#~ msgstr "不能添加好友: 无效的ID\n"
-#: core/ResourceFactory.vala:78
-#, c-format
-msgid "Toxing on Venom v.%s"
-msgstr ""
+#~ msgid "Could not add friend: %s.\n"
+#~ msgstr "不能添加好友: %s。\n"
-#: ui/ContactListWindow.vala:826
-#, c-format
-msgid "Trying to send unknown file"
-msgstr ""
+#~ msgid "Paused"
+#~ msgstr "暂停"
-#: ui/MessageTextView.vala:27
-msgid "Type your message here..."
-msgstr ""
+#~ msgid "Canceled"
+#~ msgstr "取消"
-#: core/Tools.vala:140
-msgid "Unknown error"
-msgstr ""
+#~ msgid "%s is typing..."
+#~ msgstr "%s 正在输入......"
-#: ui/ContactListWindow.vala:890
-#, c-format
-msgid "Unknown error while trying to read file: %s\n"
-msgstr ""
+#~ msgid "%s changed his status to %s\n"
+#~ msgstr "%s 切换他的状态到 %s\n"
-#: Main.vala:65
-#, c-format
-msgid "Using Gtk.TextView to display messages\n"
-msgstr ""
+#~ msgid "%s is now %s.\n"
+#~ msgstr "%s 现在 %s。\n"
-#: Main.vala:60
-#, c-format
-msgid "Using data file \"%s\"\n"
-msgstr ""
+#~ msgid "User"
+#~ msgstr "用户"
-#: ui/AddContactDialog.vala:100
-msgid "Valid ID size"
-msgstr ""
+#~ msgid "Added new friend #%i\n"
+#~ msgstr "添加新好友 #%i\n"
-#: ui/ContactListWindow.vala:461
-#, c-format
-msgid "Venom (%s)"
-msgstr ""
+#~ msgid "Background thread started.\n"
+#~ msgstr "后台线程启动。\n"
-#: ui/ConversationTextView.vala:139
-#, c-format
-msgid "[%s] "
-msgstr ""
+#~ msgid "Background thread stopped.\n"
+#~ msgstr "后台线程停止。\n"
-#: ui/ContactListWindow.vala:638
-#, c-format
-msgid "[ac] %i:%s\n"
-msgstr ""
+#~ msgid "Bad checksum"
+#~ msgstr "校验和错误"
-#: ui/ContactListWindow.vala:598
-#, c-format
-msgid "[fr] %s:%s\n"
-msgstr ""
+#~ msgid "Call contact"
+#~ msgstr "呼叫联系人"
-#: ui/ContactListWindow.vala:763
-#, c-format
-msgid "[ga] %s [%i]@%i: %s\n"
-msgstr ""
+#~ msgid "Call contact with video"
+#~ msgstr "呼叫一个视频通话"
-#: ui/ContactListWindow.vala:734
-#, c-format
-msgid "[gm] %s [%i]@%i: %s\n"
-msgstr ""
+#~ msgid "Can't create action regex: %s.\n"
+#~ msgstr "无法创建动作的正则表达式: %s。\n"
-#: ui/ContactListWindow.vala:660
-#, c-format
-msgid "[rr] %s:%u\n"
-msgstr ""
+#~ msgid "Can't send to own key"
+#~ msgstr "不能发送自己的密匙"
-#: ui/ContactListWindow.vala:656
-#, c-format
-msgid "[us] %s:%i\n"
-msgstr ""
+#~ msgid "Change _Status"
+#~ msgstr "改变状态(_S)"
-#: ui/contact_list.ui:96
-msgid "_Away"
-msgstr "离开(_A)"
+#~ msgid "Connecting to DHT Nodes:\n"
+#~ msgstr "连接到DHT节点:\n"
-#: ui/user_info_window.ui:254
-msgid "_Browse..."
-msgstr "浏览(_B)..."
+#~ msgid "Connection to DHT %s.\n"
+#~ msgstr "连接到DHT %s。\n"
-#: ui/contact_list.ui:107
-msgid "_Busy"
-msgstr "忙(_B)"
+#~ msgid "Contact accepted file sending request\n"
+#~ msgstr "联系人接受文件发送请求\n"
-#: ui/contact_list.ui:61
-msgid "_Copy ID to clipboard"
-msgstr "复制ID到剪贴板(_C)"
+#~ msgid "Copied Tox ID to clipboard\n"
+#~ msgstr "复制 TOX ID 到剪贴板\n"
-#: ui/contact_list.ui:50
-msgid "_Edit user"
-msgstr "编辑用户(_E)"
+#~ msgid "Could not change user name!\n"
+#~ msgstr "无法更改用户名称!\n"
-#: ui/add_contact_dialog.ui:94
-msgid "_Message (optional):"
-msgstr ""
+#~ msgid "Could not change user statusmessage!\n"
+#~ msgstr "无法更改用户状态消息!\n"
-#: ui/add_contact_dialog.ui:54
-msgid "_Nickname (optional):"
-msgstr ""
+#~ msgid "Could not create a new groupchat.\n"
+#~ msgstr "不能创建一个新群聊。\n"
-#: ui/contact_list.ui:85
-msgid "_Online"
-msgstr "在线(_O)"
+#~ msgid "Could not join groupchat.\n"
+#~ msgstr "不能加入群聊。\n"
-#: ui/add_contact_dialog.ui:27
-msgid "_Tox ID:"
-msgstr ""
+#~ msgid "Could not load session data (%s), creating new one.\n"
+#~ msgstr "无法加载会话数据(%s),创建一个新的。\n"
-#: ui/contact_list.ui:278
-msgid "connecting..."
-msgstr "连接中......"
+#~ msgid "Could not remove %s.\n"
+#~ msgstr "无法删除 %s.\n"
-#: ui/settings_window.ui:160
-msgid "days"
-msgstr "天记录"
+#~ msgid "Could not remove contact %i.\n"
+#~ msgstr "无法删除联系人 %i。\n"
-#: ui/settings_window.ui:127
-msgid "delete after"
-msgstr "删除早于"
+#~ msgid "Could not remove peer [%i] from groupchat #%i (no such peer)\n"
+#~ msgstr "无法删除对端 [%i] 从群聊 #%i (无此对端)\n"
-#: Main.vala:49
-#, c-format
-msgid "error: %s\n"
-msgstr ""
+#~ msgid "Default Tox DNS ID suffix:"
+#~ msgstr "缺省 Tox DNS ID 后缀:"
-#: ui/ContactListWindow.vala:668
-msgid "established"
-msgstr ""
+#~ msgid "Flash window when a new message arrives"
+#~ msgstr "一条新消息到达时闪频振动"
-#: ui/ContactListWindow.vala:569
-#, c-format
-msgid "failed to send file %s to %s"
-msgstr ""
+#~ msgid "Icon:"
+#~ msgstr "头像"
-#: ui/ContactListWindow.vala:1077
-#, c-format
-msgid "groupchat #%i"
-msgstr ""
+#~ msgid "Miscellaneous"
+#~ msgstr "杂项"
-#: ui/settings_window.ui:104
-msgid "indefinitely"
-msgstr "无限制"
+#~ msgid "Name:"
+#~ msgstr "名字"
-#: ui/ContactListWindow.vala:668
-msgid "lost"
-msgstr ""
+#~ msgid "O_ffline"
+#~ msgstr "离线(_F)"
-#: core/GroupChat.vala:56
-msgid "no one connected"
-msgstr ""
+#~ msgid "Out of memory"
+#~ msgstr "内存溢出"
-#: ui/ContactListWindow.vala:663
-msgid "offline"
-msgstr ""
+#~ msgid "Send message"
+#~ msgstr "发送消息"
-#: ui/ContactListWindow.vala:663
-msgid "online"
-msgstr ""
+#~ msgid "Settings"
+#~ msgstr "设置"
-#: ui/ContactListWindow.vala:798
-#, c-format
-msgid "received file send request friend: %i filenumber: %i filename: %s \n"
-msgstr ""
+#~ msgid "Show filesize in"
+#~ msgstr "显示文件尺寸用"
-#: ui/ContactListWindow.vala:562
-#, c-format
-msgid "sending file %s to %s\n"
-msgstr ""
+#~ msgid "Show me when others are typing"
+#~ msgstr "当其他人正在输入时我可以看到这一状态"
-#: ui/ContactListWindow.vala:1129
-#, c-format
-msgid "setting alias: %s\n"
-msgstr ""
+#~ msgid "_Away"
+#~ msgstr "离开(_A)"
-#: core/ToxDns.vala:95
-#, c-format
-msgid "tox 1 ID found: %s\n"
-msgstr ""
+#~ msgid "_Browse..."
+#~ msgstr "浏览(_B)..."
-#: core/ToxDns.vala:100
-#, c-format
-msgid "tox 2 ID found: %s %s\n"
-msgstr ""
+#~ msgid "_Busy"
+#~ msgstr "忙(_B)"
-#: ui/AboutDialog.vala:46
-msgid "translator-credits"
-msgstr ""
+#~ msgid "_Edit user"
+#~ msgstr "编辑用户(_E)"
+
+#~ msgid "_Online"
+#~ msgstr "在线(_O)"
diff --git a/scripts/builder-simplify.sh b/scripts/builder-simplify.sh
new file mode 100755
index 0000000..ccec12d
--- /dev/null
+++ b/scripts/builder-simplify.sh
@@ -0,0 +1,17 @@
+#! /bin/sh
+
+echo "running gtk-builder-tool simplify on all ui files"
+
+cd "${MESON_SOURCE_ROOT}"
+
+for i in `find src -name "*.ui"`
+do
+ echo $i
+ gtk-builder-tool simplify --replace $i
+done
+
+
+if [[ $? != 0 ]]; then
+ echo >&2 "builder-simplify command failed."
+ retval=1
+fi
diff --git a/scripts/meson.build b/scripts/meson.build
new file mode 100644
index 0000000..e289554
--- /dev/null
+++ b/scripts/meson.build
@@ -0,0 +1,3 @@
+run_target('uncrustify-diff', command : 'uncrustify-diff.sh')
+run_target('uncrustify', command : 'uncrustify.sh')
+run_target('builder-simplify', command : 'builder-simplify.sh')
diff --git a/scripts/uncrustify-diff.sh b/scripts/uncrustify-diff.sh
new file mode 100755
index 0000000..dabc2f2
--- /dev/null
+++ b/scripts/uncrustify-diff.sh
@@ -0,0 +1,10 @@
+#! /bin/sh
+
+echo "running uncrustify check on all source files"
+
+cd "${MESON_SOURCE_ROOT}"
+
+for i in `find src -name "*.vala"`
+do
+ uncrustify -c uncrustify.cfg -q -f $i | git --no-pager diff --no-index -- $i -
+done
diff --git a/scripts/uncrustify.sh b/scripts/uncrustify.sh
new file mode 100755
index 0000000..bc6481e
--- /dev/null
+++ b/scripts/uncrustify.sh
@@ -0,0 +1,10 @@
+#! /bin/sh
+
+echo "running uncrustify check on all source files"
+
+cd "${MESON_SOURCE_ROOT}"
+
+for i in `find src -name "*.vala"`
+do
+ uncrustify -c uncrustify.cfg --replace --no-backup $i
+done
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt
deleted file mode 100644
index 0018cbd..0000000
--- a/src/CMakeLists.txt
+++ /dev/null
@@ -1,245 +0,0 @@
-#
-# Copyright (C) 2013-2014 Venom authors and contributors
-#
-# This file is part of Venom.
-#
-# Venom is free software: you can redistribute it and/or modify
-# it under the terms of the GNU General Public License as published by
-# the Free Software Foundation, either version 3 of the License, or
-# (at your option) any later version.
-#
-# Venom is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with Venom. If not, see .
-#
-
-# Required cmake modules
-INCLUDE(FindVala)
-INCLUDE(${VALA_USE_FILE})
-INCLUDE(GResource)
-INCLUDE(PkgCheckModulesFullpath)
-
-# Validate version and availability through the previously defined modules
-FIND_PACKAGE(Vala "0.18.1" REQUIRED)
-FIND_PACKAGE(PkgConfig REQUIRED)
-
-# Get dependencies through pkg-config
-PKG_CHECK_MODULES_FULLPATH(GTK REQUIRED gtk+-3.0>=3.4)
-PKG_CHECK_MODULES_FULLPATH(GIO REQUIRED gio-2.0>=2.32)
-PKG_CHECK_MODULES_FULLPATH(GLIB REQUIRED glib-2.0>=2.32)
-PKG_CHECK_MODULES_FULLPATH(SQLITE REQUIRED sqlite3>=3.7)
-PKG_CHECK_MODULES_FULLPATH(JSON REQUIRED json-glib-1.0>=0.14)
-PKG_CHECK_MODULES_FULLPATH(TOX REQUIRED libtoxcore>=0.0)
-
-# use djbdns as substitute for missing dns_txt in glib 2.32
-IF(${GLIB_VERSION_MINOR} LESS 34)
- SET(ENABLE_DJBDNS ON)
-ENDIF()
-
-IF(${ENABLE_QR_ENCODE})
- PKG_CHECK_MODULES_FULLPATH(QR_ENCODE REQUIRED libqrencode>=3.1.1)
- SET(VENOM_CFLAGS_OPT ${VENOM_CFLAGS_OPT} ${QR_ENCODE_CFLAGS} ${QR_ENCODE_CFLAGS_OTHER})
- SET(VENOM_VALA_FLAGS_OPT ${VENOM_VALA_FLAGS_OPT} -D ENABLE_QR_ENCODE)
- SET(VENOM_LIBRARIES_OPT ${VENOM_LIBRARIES_OPT} ${QR_ENCODE_LIBRARIES})
-ENDIF()
-
-IF(${ENABLE_DJBDNS})
- INCLUDE(FindDJBDns)
- SET(VENOM_CFLAGS_OPT ${VENOM_CFLAGS_OPT} ${DJBDNS_CFLAGS})
- SET(VENOM_VALA_FLAGS_OPT ${VENOM_VALA_FLAGS_OPT} -D ENABLE_DJBDNS)
- SET(VENOM_LIBRARIES_OPT ${VENOM_LIBRARIES_OPT} ${DJBDNS_LIBRARIES})
-ENDIF()
-
-IF(${ENABLE_LIBNOTIFY})
- PKG_CHECK_MODULES_FULLPATH(LIBNOTIFY REQUIRED libnotify>=0.7.3)
- SET(VENOM_CFLAGS_OPT ${VENOM_CFLAGS_OPT} ${LIBNOTIFY_CFLAGS})
- SET(VENOM_VALA_FLAGS_OPT ${VENOM_VALA_FLAGS_OPT} -D ENABLE_LIBNOTIFY)
- SET(VENOM_LIBRARIES_OPT ${VENOM_LIBRARIES_OPT} ${LIBNOTIFY_LIBRARIES})
-ENDIF()
-
-IF(CMAKE_BUILD_TYPE STREQUAL "Debug" OR CMAKE_BUILD_TYPE STREQUAL "DEBUG")
- MESSAGE("Debug build, setting debug flags")
- SET(VENOM_VALA_FLAGS_OPT ${VENOM_VALA_FLAGS_OPT} -D DEBUG)
-ENDIF()
-
-# Set a variable defining our minimal version of glib
-SET(TARGET_GLIB ${GLIB_VERSION_MAJOR}.${GLIB_VERSION_MINOR})
-
-# Workaround for libtoxcore and libsodium not providing info on
-# all needed static libraries in their pkg-config files
-# see https://github.com/irungentoo/ProjectTox-Core/issues/705
-IF(LINK_TOX_STATIC)
- IF(WIN32)
- SET(TOX_LIBRARIES ${TOX_LIBRARIES} m.a ws2_32.a)
- ELSE(WIN32)
- SET(TOX_LIBRARIES ${TOX_LIBRARIES} m.so)
- ENDIF(WIN32)
-ENDIF(LINK_TOX_STATIC)
-IF(LINK_GTK_STATIC)
- IF(WIN32)
- SET(GTK_LIBRARIES ${GTK_LIBRARIES} usp10.a iphlpapi.a)
- ENDIF(WIN32)
-ENDIF(LINK_GTK_STATIC)
-IF(LINK_GIO_STATIC)
- IF(WIN32)
- SET(GIO_LIBRARIES ${GIO_LIBRARIES} dnsapi.a iconv.a)
- ENDIF(WIN32)
-ENDIF(LINK_GIO_STATIC)
-
-SET(GETTEXT_CFLAGS "-DGETTEXT_PACKAGE=\\\"${GETTEXT_PACKAGE}\\\"")
-
-# add cflags and cflags_other of all dependencies to our cflags
-SET(CMAKE_C_FLAGS ${CMAKE_C_FLAGS} ${GETTEXT_CFLAGS}
- ${GTK_CFLAGS} ${GTK_CFLAGS_OTHER}
- ${GIO_CFLAGS} ${GIO_CFLAGS_OTHER}
- ${GLIB_CFLAGS} ${GLIB_CFLAGS_OTHER}
- ${SQLITE_CFLAGS} ${SQLITE_CFLAGS_OTHER}
- ${JSON_CFLAGS} ${JSON_CFLAGS_OTHER}
- ${TOX_CFLAGS} ${TOX_CFLAGS_OTHER}
- ${VENOM_CFLAGS_OPT}
-)
-
-# since pkg_check_modules returns semicolon
-# separated *_c_flags, we have to remove those
-STRING(REPLACE ";" " " CMAKE_C_FLAGS "${CMAKE_C_FLAGS}")
-
-# replace the annotated variables in config.h.in and copy it to config.h
-CONFIGURE_FILE( config.h.in config.h )
-
-# define our source files
-SET( VENOM_SRC
- Main.vala
- core/Contact.vala
- core/ContactStorage.vala
- core/DhtNode.vala
- core/DhtNodeStorage.vala
- core/FileTransfer.vala
- core/GroupChat.vala
- core/GroupChatContact.vala
- core/Logger.vala
- core/MessageLog.vala
- core/Message.vala
- core/Notification.vala
- core/ResourceFactory.vala
- core/Settings.vala
- core/SqliteTools.vala
- core/Tools.vala
- core/ToxDns.vala
- core/ToxSession.vala
- core/User.vala
- ui/AboutDialog.vala
- ui/AddContactDialog.vala
- ui/ChatMessage.vala
- ui/Client.vala
- ui/ContactFilter.vala
- ui/ContactListCellRenderer.vala
- ui/ContactListTreeView.vala
- ui/ContactListWindow.vala
- ui/ConversationTextView.vala
- ui/ConversationView.vala
- ui/ConversationWidget.vala
- ui/EditableLabel.vala
- ui/FileTransferChatEntry.vala
- ui/GroupConversationSidebar.vala
- ui/GroupConversationWidget.vala
- ui/MessageTextView.vala
- ui/PinDialog.vala
- ui/SearchEntry.vala
- ui/UserInfoWindow.vala
- ui/UITools.vala
- ui/SettingsWindow.vala
-)
-
-SET( VENOM_GLADE
- src/ui/add_contact_dialog.ui
- src/ui/chat_filetransfer.ui
- src/ui/contact_list.ui
- src/ui/conversation_window.ui
- src/ui/settings_window.ui
- src/ui/user_info_window.ui
-)
-
-IF (XGETTEXT_FOUND)
- # create new pot file with "make pot_file"
- GETTEXT_CREATE_POT(${GETTEXT_PACKAGE}.pot OPTION ${XGETTEXT_OPTIONS} SRC ${VENOM_SRC} GLADE ${VENOM_GLADE})
-ENDIF()
-
-# precompile all vala code to c via valac
-VALA_PRECOMPILE( VALA_C_VENOM
- ${VENOM_SRC}
- PACKAGES
- config
- djbdns
- gio-2.0
- glib-2.0
- gtk+-3.0
- json-glib-1.0
- libnotify
- libqrencode
- sqlite3
- tox-1.0
- OPTIONS
- --target-glib=${TARGET_GLIB}
- --thread
- --vapidir=${CMAKE_SOURCE_DIR}/src/vapi
- ${VENOM_VALA_FLAGS_OPT}
- CUSTOM_VAPIS
- GENERATE_VAPI
- GENERATE_HEADER
-)
-
-# compile glib resource files to c code
-GLIB_COMPILE_RESOURCES( GLIB_RESOURCES_VENOM
- SOURCE
- ui/venom.gresource.xml
- pixmaps/venom_pixmaps.gresource.xml
-)
-
-# compile the main executable
-ADD_EXECUTABLE( venom
- ${VALA_C_VENOM}
- ${GLIB_RESOURCES_VENOM}
- ${VENOM_RESOURCE_FILE}
-)
-
-# link the main executable to our dependencies
-TARGET_LINK_LIBRARIES( venom
- ${VENOM_LIBRARIES_OPT}
- ${TOX_LIBRARIES}
- ${SQLITE_LIBRARIES}
- ${GIO_LIBRARIES}
- ${GLIB_LIBRARIES}
- ${GTK_LIBRARIES}
- ${JSON_LIBRARIES}
-)
-
-INSTALL(TARGETS venom RUNTIME DESTINATION ${CMAKE_INSTALL_SYSTEM_RUNTIME_DESTINATION})
-
-# add tests
-ADD_SUBDIRECTORY(testing)
-
-# Summary of optional features
-MESSAGE("Optional features / dependencies:")
-SET(DJBDNS_DESCRIPTION "ENABLE_DJBDNS - resolve tox dns ids using djbdns (required for glib <= 2.32)")
-IF(${ENABLE_DJBDNS})
- MESSAGE(" [X] ${DJBDNS_DESCRIPTION}")
-ELSE()
- MESSAGE(" [ ] ${DJBDNS_DESCRIPTION}")
-ENDIF()
-SET(QR_ENCODE_DESCRIPTION "ENABLE_QR_ENCODE - show QR codes (requires libqrencode)")
-IF(${ENABLE_QR_ENCODE})
- MESSAGE(" [X] ${QR_ENCODE_DESCRIPTION}")
-ELSE()
- MESSAGE(" [ ] ${QR_ENCODE_DESCRIPTION}")
-ENDIF()
-SET(LIBNOTIFY_DESCRIPTION "ENABLE_LIBNOTIFY - libnotify notification support")
-IF(${ENABLE_LIBNOTIFY})
- MESSAGE(" [X] ${LIBNOTIFY_DESCRIPTION}")
-ELSE()
- MESSAGE(" [ ] ${LIBNOTIFY_DESCRIPTION}")
-ENDIF()
-# vim:set ts=2 sw=2 et:
diff --git a/src/Main.vala b/src/Main.vala
index 00a0f2f..c24d839 100644
--- a/src/Main.vala
+++ b/src/Main.vala
@@ -1,7 +1,7 @@
/*
* Main.vala
*
- * Copyright (C) 2013-2014 Venom authors and contributors
+ * Copyright (C) 2013-2018 Venom authors and contributors
*
* This file is part of Venom.
*
@@ -20,77 +20,11 @@
*/
namespace Venom {
- public class Main : GLib.Object {
- private static string? datafile = null;
- private static bool offline = false;
- private static bool textview = false;
- private static bool version = false;
- private const OptionEntry[] option_entries = {
- { "file" , 'f', 0, OptionArg.FILENAME, ref datafile , "Set the location of the tox data file", "" },
- { "loglevel", 'l', 0, OptionArg.CALLBACK, (void*) parse_loglevel, "Set level of messages to log", "" },
- { "offline" , 0 , 0, OptionArg.NONE , ref offline , "Start in offline mode", null },
- { "textview", 0 , 0, OptionArg.NONE , ref textview , "Use textview to display messages", null },
- { "version" , 'V', 0, OptionArg.NONE , ref version , "Display version number", null },
- { null }
- };
+ int main (string[] args) {
+ GLib.Intl.bindtextdomain(Config.GETTEXT_PACKAGE, Config.GETTEXT_PATH);
+ GLib.Intl.bind_textdomain_codeset(Config.GETTEXT_PACKAGE, "utf-8");
+ GLib.Intl.textdomain(Config.GETTEXT_PACKAGE);
- public static bool parse_loglevel (string name, string? val, ref OptionError error) throws OptionError {
- if (val == null) {
- return true;
- }
- Regex regex;
- try {
- regex = new GLib.Regex("^[0-9]+$");
- } catch {
- Logger.log(LogLevel.FATAL, "could not create regex needed for number parsing");
- return true;
- }
-
- if (!regex.match (val, 0, null)) {
- throw new OptionError.BAD_VALUE (_("'%s' not a positive number"), val);
- }
- Logger.displayed_level = (LogLevel)int.parse(val);
- return true;
- }
-
- public static int main (string[] args) {
- GLib.Intl.setlocale(GLib.LocaleCategory.MESSAGES, "");
- GLib.Intl.textdomain(Config.GETTEXT_PACKAGE);
- GLib.Intl.bind_textdomain_codeset(Config.GETTEXT_PACKAGE, "utf-8");
- //FIXME see if this is needed on windows
- //GLib.Intl.bindtextdomain(Config.GETTEXT_PACKAGE, Config.GETTEXT_PATH);
- GLib.OptionContext option_context = new GLib.OptionContext("");
- option_context.set_help_enabled(true);
- option_context.add_main_entries(option_entries, null);
- try {
- option_context.parse(ref args);
- } catch (GLib.OptionError e) {
- stdout.printf(_("error: %s\n"), e.message);
- stdout.printf(_("Run '%s --help' to see a full list of available command line options.\n"), args[0]);
- return -1;
- }
-
- if(version) {
- stdout.printf("%s %s\n", args[0], Config.VERSION);
- return 0;
- }
-
- if(datafile != null) {
- Logger.log(LogLevel.INFO, "Using data file \"" + datafile + "\"");
- ResourceFactory.instance.data_filename = datafile;
- }
-
- if(textview) {
- Logger.log(LogLevel.INFO, "Using Gtk.TextView to display messages");
- ResourceFactory.instance.textview_mode = true;
- }
-
- if(offline) {
- Logger.log(LogLevel.INFO, "Starting in offline mode");
- ResourceFactory.instance.offline_mode = true;
- }
-
- return new Client().run(args);
- }
+ return new Application().run(args);
}
}
diff --git a/src/core/AVManager.vala b/src/core/AVManager.vala
new file mode 100644
index 0000000..825d047
--- /dev/null
+++ b/src/core/AVManager.vala
@@ -0,0 +1,814 @@
+/*
+ * AVManager.vala
+ *
+ * Copyright (C) 2013-2014 Venom authors and contributors
+ *
+ * This file is part of Venom.
+ *
+ * Venom is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Venom is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Venom. If not, see .
+ */
+
+namespace Venom {
+ public errordomain AVManagerError {
+ INIT,
+ PIPELINE
+ }
+
+ public struct AudioCallInfo {
+ bool active;
+ bool muted;
+ int volume;
+ }
+
+ public struct VideoCallInfo {
+ bool active;
+ }
+
+ public enum AudioStatusChangeType {
+ START,
+ START_PREVIEW,
+ END,
+ END_PREVIEW,
+ MUTE,
+ VOLUME,
+ KILL
+ }
+
+ public enum VideoStatusChangeType {
+ START,
+ START_PREVIEW,
+ END,
+ END_PREVIEW,
+ KILL
+ }
+
+ public struct AVStatusChange {
+ int type;
+ int32 call_index;
+ int var1;
+ }
+
+ public class AVManager {
+
+ private const string PIPELINE_IN = "audioPipelineIn";
+ private const string AUDIO_SOURCE_IN = "audioSourceIn";
+ private const string AUDIO_SINK_IN = "audioSinkIn";
+ private const string AUDIO_VOLUME_IN = "audioVolumeIn";
+
+ private const string PIPELINE_OUT = "audioPipelineOut";
+ private const string AUDIO_SOURCE_OUT = "audioSourceOut";
+ private const string AUDIO_SINK_OUT = "audioSinkOut";
+ private const string AUDIO_VOLUME_OUT = "audioVolumeOut";
+
+ private const string VIDEO_PIPELINE_IN = "videoPipelineIn";
+ private const string VIDEO_SOURCE_IN = "videoSourceIn";
+ private const string VIDEO_CONVERTER = "videoConverter";
+ private const string VIDEO_SINK_IN = "videoSinkIn";
+
+ private const string VIDEO_PIPELINE_OUT = "videoPipelineOut";
+ private const string VIDEO_SOURCE_OUT = "videoSourceOut";
+ private const string VIDEO_CONVERTER_OUT = "videoConverterOut";
+ private const string VIDEO_SINK_OUT = "videoSinkOut";
+
+ private const string VIDEO_CAPS_OUT = "video/x-raw-yuv,format=(fourcc)I420,width=640,height=480";
+
+ private const int MAX_CALLS = 16;
+
+ private AsyncQueue audio_status_changes = new AsyncQueue();
+ private AsyncQueue video_status_changes = new AsyncQueue();
+
+ private Gst.Pipeline pipeline_in;
+ private Gst.AppSrc audio_source_in;
+ private Gst.Element audio_sink_in;
+ private Gst.Element audio_volume_in;
+
+ private Gst.Pipeline pipeline_out;
+ private Gst.Element audio_source_out;
+ private Gst.AppSink audio_sink_out;
+ private Gst.Element audio_volume_out;
+
+ private Gst.Pipeline video_pipeline_in;
+ private Gst.AppSrc video_source_in;
+ private Gst.Element video_sink_in;
+
+ private Gst.Pipeline video_pipeline_out;
+ private Gst.Element video_source_out;
+ private Gst.Element video_converter_out;
+ private Gst.AppSink video_sink_out;
+
+ private Gst.Bus audio_in_bus;
+ private Gst.Bus audio_out_bus;
+ private Gst.Bus video_in_bus;
+ private Gst.Bus video_out_bus;
+
+ private Thread audio_thread = null;
+ private Thread video_thread = null;
+
+ // settings in use by audio in pipeline
+ private ToxAV.CodecSettings current_audio_settings = ToxAV.DefaultCodecSettings;
+ // settings in use by out pipeline
+ private ToxAV.CodecSettings default_settings = ToxAV.DefaultCodecSettings;
+ private ToxSession _tox_session = null;
+ private unowned ToxAV.ToxAV toxav = null;
+ public ToxSession tox_session {
+ get {
+ return _tox_session;
+ } set {
+ _tox_session = value;
+ toxav = _tox_session.toxav_handle;
+ register_callbacks();
+ }
+ }
+
+ public static AVManager instance { get; private set; }
+
+ public static void init() throws AVManagerError {
+//#if DEBUG
+// instance = new AVManager({"", "--gst-debug-level=3"});
+//#else
+ instance = new AVManager({ "" });
+//#endif
+ }
+
+ public static void free() {
+ Logger.log(LogLevel.DEBUG, "AVManager free called");
+ instance = null;
+ }
+
+ private AVManager(string[] args) throws AVManagerError {
+ // Initialize Gstreamer
+ try {
+ if (!Gst.init_check(ref args)) {
+ throw new AVManagerError.INIT("Gstreamer initialization failed.");
+ }
+ } catch (Error e) {
+ throw new AVManagerError.INIT(e.message);
+ }
+ Logger.log(LogLevel.INFO, "Gstreamer initialized");
+
+ // input audio pipeline
+ try {
+ pipeline_in = Gst.parse_launch("appsrc name=" + AUDIO_SOURCE_IN +
+ " ! audioconvert" +
+ " ! audioresample" +
+ " ! volume name=" + AUDIO_VOLUME_IN +
+ " ! openalsink name=" + AUDIO_SINK_IN) as Gst.Pipeline;
+ } catch (Error e) {
+ throw new AVManagerError.PIPELINE("Error creating the audio input pipeline: " + e.message);
+ }
+ audio_source_in = pipeline_in.get_by_name(AUDIO_SOURCE_IN) as Gst.AppSrc;
+ audio_volume_in = pipeline_in.get_by_name(AUDIO_VOLUME_IN);
+ audio_sink_in = pipeline_in.get_by_name(AUDIO_SINK_IN);
+
+ audio_in_bus = pipeline_in.get_bus();
+
+ // output audio pipeline
+ try {
+ pipeline_out = Gst.parse_launch("pulsesrc name=" + AUDIO_SOURCE_OUT +
+ " ! volume name=" + AUDIO_VOLUME_OUT +
+ " ! appsink name=" + AUDIO_SINK_OUT) as Gst.Pipeline;
+ } catch (Error e) {
+ throw new AVManagerError.PIPELINE("Error creating the audio output pipeline: " + e.message);
+ }
+ audio_source_out = pipeline_out.get_by_name(AUDIO_SOURCE_OUT);
+ audio_volume_out = pipeline_out.get_by_name(AUDIO_VOLUME_OUT);
+ audio_sink_out = pipeline_out.get_by_name(AUDIO_SINK_OUT) as Gst.AppSink;
+
+ audio_out_bus = pipeline_out.get_bus();
+
+ // input video pipeline
+ try {
+ video_pipeline_in = Gst.parse_launch("appsrc name=" + VIDEO_SOURCE_IN +
+ " ! ffmpegcolorspace name=" + VIDEO_CONVERTER +
+ " ! autovideosink name=" + VIDEO_SINK_IN) as Gst.Pipeline;
+ } catch (Error e) {
+ throw new AVManagerError.PIPELINE("Error creating the video input pipeline: " + e.message);
+ }
+ video_source_in = video_pipeline_in.get_by_name(VIDEO_SOURCE_IN) as Gst.AppSrc;
+ video_sink_in = video_pipeline_in.get_by_name(VIDEO_SINK_IN);
+
+ video_in_bus = video_pipeline_in.get_bus();
+
+ // output video pipeline
+ try {
+ video_pipeline_out = Gst.parse_launch("autovideosrc name=" + VIDEO_SOURCE_OUT +
+ " ! ffmpegcolorspace name=" + VIDEO_CONVERTER_OUT +
+ " ! videoscale" +
+ " ! appsink name=" + VIDEO_SINK_OUT) as Gst.Pipeline;
+ } catch (Error e) {
+ throw new AVManagerError.PIPELINE("Error creating the video output pipeline: " + e.message);
+ }
+ video_source_out = video_pipeline_out.get_by_name(VIDEO_SOURCE_OUT);
+ video_converter_out = video_pipeline_out.get_by_name(VIDEO_CONVERTER_OUT);
+ video_sink_out = video_pipeline_out.get_by_name(VIDEO_SINK_OUT) as Gst.AppSink;
+
+ video_out_bus = video_pipeline_out.get_bus();
+
+ //set the bus callbacks
+ audio_in_bus.add_watch( bus_callback);
+ audio_out_bus.add_watch(bus_callback);
+ video_in_bus.add_watch( bus_callback);
+ video_out_bus.add_watch(bus_callback);
+
+ // caps
+ Gst.Caps caps = Gst.Caps.from_string(get_audio_caps_from_codec_settings(ref default_settings));
+ Gst.Caps vcaps_in = Gst.Caps.from_string(get_video_in_caps_from_dimensions(640, 480));
+ Gst.Caps vcaps_out = Gst.Caps.from_string(VIDEO_CAPS_OUT);
+ Logger.log(LogLevel.INFO, "Audio caps are [" + caps.to_string() + "]");
+ Logger.log(LogLevel.INFO, "Video(IN) caps are [" + vcaps_in.to_string() + "]");
+ Logger.log(LogLevel.INFO, "Video(OUT) caps are [" + vcaps_out.to_string() + "]");
+
+ audio_source_in.caps = caps;
+ audio_sink_out.caps = caps;
+
+ video_source_in.caps = vcaps_in;
+ video_sink_out.caps = vcaps_out;
+
+ //audio_sink_out.blocksize = (ToxAV.DefaultCodecSettings.audio_frame_duration * ToxAV.DefaultCodecSettings.audio_sample_rate) / 1000 * 2;
+ //audio_sink_out.drop = true;
+ //audio_sink_out.max_buffers = 2;
+ //audio_sink_out.max_lateness = 1000; // buffers older than 1 msec will be dropped
+
+ audio_source_in.is_live = true;
+ audio_source_in.min_latency = 0;
+ audio_source_in.do_timestamp = false;
+
+ ((Gst.BaseSrc)audio_source_out).blocksize = (ToxAV.DefaultCodecSettings.audio_frame_duration * ToxAV.DefaultCodecSettings.audio_sample_rate) / 1000 * 2;
+ //((Gst.BaseSrc)video_source_out).blocksize = (ToxAV.DefaultCodecSettings.video_bitrate) ;
+
+ Settings.instance.bind_property(Settings.MIC_VOLUME_KEY, audio_volume_out, "volume", BindingFlags.SYNC_CREATE);
+ }
+
+ ~AVManager() {
+ Logger.log(LogLevel.INFO, "AVManager destructor called");
+ audio_status_changes.push( AVStatusChange() {
+ type = VideoStatusChangeType.KILL
+ });
+ video_status_changes.push( AVStatusChange() {
+ type = VideoStatusChangeType.KILL
+ });
+
+ destroy_audio_pipeline();
+ destroy_video_pipeline();
+
+ join();
+
+ Gst.deinit();
+ Logger.log(LogLevel.INFO, "Gstreamer deinitialized");
+ }
+
+ private bool bus_callback(Gst.Bus bus, Gst.Message message) {
+ Error e;
+ if (bus == audio_in_bus) {
+ Logger.log(LogLevel.DEBUG, "Audio_in_bus with message: " + message.type.get_name());
+ } else if (bus == audio_out_bus) {
+ Logger.log(LogLevel.DEBUG, "Audio_out_bus with message: " + message.type.get_name());
+ } else if (bus == video_in_bus) {
+ Logger.log(LogLevel.DEBUG, "Video_in_bus with message: " + message.type.get_name());
+ } else if (bus == video_out_bus) {
+ Logger.log(LogLevel.DEBUG, "Video_out_bus with message: " + message.type.get_name());
+
+ switch (message.type) {
+ case Gst.MessageType.ERROR:
+ message.parse_error(out e, null);
+ Logger.log(LogLevel.ERROR, e.message);
+ video_pipeline_out.set_state(Gst.State.NULL);
+ break;
+ case Gst.MessageType.WARNING:
+ message.parse_warning(out e, null);
+ Logger.log(LogLevel.WARNING, e.message);
+ break;
+ case Gst.MessageType.EOS:
+ Logger.log(LogLevel.DEBUG, message.src.name);
+ break;
+
+ case Gst.MessageType.STATE_CHANGED:
+ // We are only interested in state-changed messages from the pipeline:
+ Gst.State old_state;
+ Gst.State new_state;
+ Gst.State pending_state;
+
+ message.parse_state_changed(out old_state, out new_state, out pending_state);
+ Logger.log(LogLevel.DEBUG, "Pipeline state changed from %d to %d:\n".printf(
+ old_state, new_state)
+ );
+ break;
+
+ default:
+ break;
+ }
+ }
+ return true;
+ }
+
+ private void audio_receive_callback(ToxAV.ToxAV toxav, int32 call_index, int16[] samples) {
+ //Logger.log(LogLevel.DEBUG, "Received audio samples (%d bytes)".printf(samples.length * 2));
+ set_audio_caps(call_index);
+ play_audio_buffer(samples, samples.length);
+ }
+
+ private void video_receive_callback(ToxAV.ToxAV toxav, int32 call_index, Vpx.Image frame) {
+ Logger.log(LogLevel.DEBUG, "Got video frame, of size: %u".printf(frame.d_w * frame.d_h));
+ set_video_in_caps(frame.d_w, frame.d_h);
+ video_buffer_in(frame);
+ }
+
+ private void register_callbacks() {
+ toxav.register_audio_recv_callback(audio_receive_callback);
+ toxav.register_video_recv_callback(video_receive_callback);
+ }
+
+ private void destroy_audio_pipeline() {
+ pipeline_in.set_state(Gst.State.NULL);
+ pipeline_out.set_state(Gst.State.NULL);
+ Logger.log(LogLevel.INFO, "Audio pipeline destroyed");
+ }
+
+ private void set_audio_pipeline_playing() {
+ pipeline_in.set_state(Gst.State.PLAYING);
+ pipeline_out.set_state(Gst.State.PLAYING);
+ Logger.log(LogLevel.INFO, "Audio pipeline set to playing");
+ }
+
+ private void set_video_pipeline_playing() {
+ video_pipeline_in.set_state(Gst.State.PLAYING);
+ video_pipeline_out.set_state(Gst.State.PLAYING);
+ Logger.log(LogLevel.INFO, "Video pipeline set to playing");
+ }
+
+ private void destroy_video_pipeline() {
+ video_pipeline_in.set_state(Gst.State.NULL);
+ video_pipeline_out.set_state(Gst.State.NULL);
+ Logger.log(LogLevel.INFO, "Video pipeline destroyed");
+ }
+
+ private static string get_audio_caps_from_codec_settings(ref ToxAV.CodecSettings settings) {
+ return "audio/x-raw-int,channels=(int)%u,rate=(int)%u,signed=(boolean)true,width=(int)16,depth=(int)16,endianness=(int)1234".printf(settings.audio_channels, settings.audio_sample_rate);
+ }
+
+ private static string get_video_in_caps_from_dimensions(uint w, uint h, uint framerate = 24) {
+ return "video/x-raw-yuv,format=(fourcc)I420,width=%u,height=%u,framerate=%u/1".printf(w, h, framerate);
+ }
+
+ uint w_ = 640;
+ uint h_ = 480;
+ private void set_video_in_caps(uint w, uint h) {
+ if (h == h_ && w == w_) {
+ return;
+ }
+ w_ = w;
+ h_ = h;
+ string caps_string = get_video_in_caps_from_dimensions(w_, h_);
+ Logger.log(LogLevel.INFO, "Changing video caps to " + caps_string);
+ video_pipeline_in.set_state(Gst.State.NULL);
+ video_source_in.caps = Gst.Caps.from_string(caps_string);
+ video_pipeline_in.set_state(Gst.State.PLAYING);
+ }
+
+ private void set_audio_caps(int32 call_index) {
+ ToxAV.CodecSettings settings = ToxAV.CodecSettings();
+ ToxAV.AV_Error ret = toxav.get_peer_csettings(call_index, 0, ref settings);
+
+ if (ret != ToxAV.AV_Error.NONE) {
+ Logger.log(LogLevel.DEBUG, "Could not acquire codec settings for contact %i, assuming default settings".printf(call_index));
+ settings = ToxAV.DefaultCodecSettings;
+ }
+
+ if (settings.audio_channels != current_audio_settings.audio_channels ||
+ settings.audio_sample_rate != current_audio_settings.audio_sample_rate) {
+ current_audio_settings = settings;
+ string caps_string = get_audio_caps_from_codec_settings(ref settings);
+ Logger.log(LogLevel.INFO, "Changing caps to " + caps_string);
+ audio_source_in.caps = Gst.Caps.from_string(caps_string);
+ }
+ }
+
+ private void play_audio_buffer(int16[] buffer, int buffer_length) {
+ int len = buffer_length * 2;
+ Gst.Buffer gst_buf = new Gst.Buffer.and_alloc(len);
+ Memory.copy(gst_buf.data, buffer, len);
+ gst_buf.duration = -1; // settings.audio_frame_duration * Gst.MSECOND;
+ gst_buf.timestamp = -1;
+ audio_source_in.push_buffer(gst_buf);
+ }
+
+ private int record_audio_buffer(ref int16[] dest) {
+ Gst.Buffer gst_buf = audio_sink_out.pull_buffer();
+ //Allocate the new buffer here, we will return this buffer (it is dest)
+ int len = int.min(gst_buf.data.length, dest.length * 2);
+ Memory.copy(dest, gst_buf.data, len);
+ //Logger.log(LogLevel.DEBUG, "pulled %i bytes from OUT pipeline".printf(len));
+ return len / 2;
+ }
+
+ private void video_buffer_in(Vpx.Image frame) {
+ int w = (int) frame.d_w, h = (int) frame.d_h;
+ //Logger.log(LogLevel.DEBUG, "received new vpx frame of size %ix%i".printf(w, h));
+ int comp_offset_y = Gst.video_format_get_component_offset(Gst.VideoFormat.I420, 0, w, h);
+ int comp_offset_u = Gst.video_format_get_component_offset(Gst.VideoFormat.I420, 1, w, h);
+ int comp_offset_v = Gst.video_format_get_component_offset(Gst.VideoFormat.I420, 2, w, h);
+ //Logger.log(LogLevel.DEBUG, "comp_offset_y: %i, comp_offset_u: %i, comp_offset_v: %i".printf(comp_offset_y, comp_offset_u, comp_offset_v));
+ int row_stride_y = Gst.video_format_get_row_stride(Gst.VideoFormat.I420, 0, w);
+ int row_stride_u = Gst.video_format_get_row_stride(Gst.VideoFormat.I420, 1, w);
+ int row_stride_v = Gst.video_format_get_row_stride(Gst.VideoFormat.I420, 2, w);
+ //Logger.log(LogLevel.DEBUG, "row_stride_y: %i, row_stride_u: %i, row_stride_v: %i".printf(row_stride_y, row_stride_u, row_stride_v));
+ int pixel_stride_y = Gst.video_format_get_pixel_stride(Gst.VideoFormat.I420, 0);
+ int pixel_stride_u = Gst.video_format_get_pixel_stride(Gst.VideoFormat.I420, 1);
+ int pixel_stride_v = Gst.video_format_get_pixel_stride(Gst.VideoFormat.I420, 2);
+ //Logger.log(LogLevel.DEBUG, "pixel_stride_y: %i, pixel_stride_u: %i, pixel_stride_v: %i".printf(pixel_stride_y, pixel_stride_u, pixel_stride_v));
+
+ Gst.Buffer gst_buf = new Gst.Buffer.and_alloc(Gst.video_format_get_size(Gst.VideoFormat.I420, w, h));
+ //Logger.log(LogLevel.DEBUG, "Created buffer of size %i".printf(gst_buf.data.length));
+ unowned uint8[] y = gst_buf.data[comp_offset_y : comp_offset_u];
+ unowned uint8[] u = gst_buf.data[comp_offset_u : comp_offset_v];
+ unowned uint8[] v = gst_buf.data[comp_offset_v : gst_buf.data.length];
+
+ int i, j;
+ int offset_y = 0;
+ for (i = 0; i < frame.d_h; ++i) {
+ offset_y = i * row_stride_y;
+ for (j = 0; j < frame.d_w; ++j) {
+ y[offset_y] = *(*(frame.planes + 0) + ((i * frame.stride[0]) + j));
+ offset_y += pixel_stride_y;
+ }
+ }
+
+ int offset_u = 0, offset_v = 0;
+ for (i = 0; i < frame.d_h / 2; ++i) {
+ offset_u = i * row_stride_u;
+ offset_v = i * row_stride_v;
+ for (j = 0; j < frame.d_w / 2; ++j) {
+ v[offset_v] = *(*(frame.planes + 1) + ((i * frame.stride[1]) + j));
+ u[offset_u] = *(*(frame.planes + 2) + ((i * frame.stride[2]) + j));
+ offset_v += pixel_stride_v;
+ offset_u += pixel_stride_u;
+ }
+ }
+
+ video_source_in.push_buffer(gst_buf);
+ Logger.log(LogLevel.DEBUG, "pushed %u bytes to VIDEO_IN pipeline".printf(gst_buf.data.length));
+ }
+
+ private Vpx.Image ? make_vpx_image() {
+ Gst.Buffer gst_buf = video_sink_out.pull_buffer();
+ if (gst_buf == null) {
+ return null;
+ }
+ //Logger.log(LogLevel.DEBUG, "pulled %i bytes form VIDEO_OUT pipeline".printf(gst_buf.data.length));
+
+ unowned Gst.Structure structure = gst_buf.caps.get_structure(0);
+ int height = 0, width = 0;
+ if (!structure.get_int("height", out height) || !structure.get_int("width", out width)) {
+ Logger.log(LogLevel.ERROR, "Error retrieving height and width from caps: " + gst_buf.caps.to_string());
+ return null;
+ }
+
+ Vpx.Image my_image = Vpx.Image.wrap(null, Vpx.ImageFormat.I420, width, height, 0, gst_buf.data);
+
+ // switch u and v
+ uint8* temp = my_image.planes[1];
+ my_image.planes[1] = my_image.planes[2];
+ my_image.planes[2] = temp;
+
+ return my_image;
+ }
+
+ private int video_thread_fun() {
+ Logger.log(LogLevel.INFO, "starting video thread...");
+ set_video_pipeline_playing();
+
+ VideoCallInfo[] calls = new VideoCallInfo[MAX_CALLS];
+ ToxAV.AV_Error prep_frame_ret = 0, send_video_ret = 0;
+ uint8[] video_enc_buffer = new uint8[800 * 600 * 4];
+ int number_of_calls = 0;
+ bool preview = false;
+
+ bool running = true;
+ while (running) {
+ AVStatusChange ? c = video_status_changes.try_pop();
+ if (c != null) {
+ switch (c.type) {
+ case VideoStatusChangeType.START:
+ Logger.log(LogLevel.DEBUG, "Starting video session #%i".printf(c.call_index));
+ if (calls[c.call_index].active == false) {
+ number_of_calls++;
+ }
+ calls[c.call_index].active = true;
+ break;
+ case VideoStatusChangeType.START_PREVIEW:
+ Logger.log(LogLevel.DEBUG, "Starting video preview");
+ preview = true;
+ break;
+ case VideoStatusChangeType.END:
+ Logger.log(LogLevel.DEBUG, "Ending video session %i".printf(c.call_index));
+ if (calls[c.call_index].active == true) {
+ number_of_calls--;
+ }
+ calls[c.call_index].active = false;
+ break;
+ case VideoStatusChangeType.END_PREVIEW:
+ Logger.log(LogLevel.DEBUG, "Stopping video preview %i".printf(c.call_index));
+ preview = false;
+ break;
+ case VideoStatusChangeType.KILL:
+ Logger.log(LogLevel.DEBUG, "Video thread received kill message");
+ running = false;
+ continue;
+ default:
+ Logger.log(LogLevel.ERROR, "unknown video status change type");
+ break;
+ }
+ }
+
+ // block until something gets pushed to video_status_changes
+ if (number_of_calls == 0 && !preview) {
+ destroy_video_pipeline();
+ c = video_status_changes.pop();
+ video_status_changes.push(c);
+ set_video_pipeline_playing();
+ continue;
+ }
+
+ Vpx.Image out_image = make_vpx_image();
+ if (out_image == null) {
+ // either eos or pipeline stopped
+ Logger.log(LogLevel.DEBUG, "Pulled null buffer from video device");
+ Thread.usleep(10000);
+ continue;
+ }
+
+ if (preview) {
+ video_buffer_in(out_image);
+ }
+
+ for (int i = 0; i < MAX_CALLS; i++) {
+ if (calls[i].active) {
+ prep_frame_ret = toxav.prepare_video_frame(i, video_enc_buffer, out_image);
+ if (prep_frame_ret <= 0) {
+ Logger.log(LogLevel.WARNING, "prepare_video_frame returned an error: " + prep_frame_ret.to_string());
+ } else {
+ send_video_ret = toxav.send_video(i, video_enc_buffer, prep_frame_ret);
+ if (send_video_ret != ToxAV.AV_Error.NONE) {
+ Logger.log(LogLevel.WARNING, "send_video returned " + send_video_ret.to_string());
+ }
+ }
+ }
+ }
+ }
+ Logger.log(LogLevel.INFO, "stopping video thread...");
+ destroy_video_pipeline();
+ return 0;
+ }
+
+ private int audio_thread_fun() {
+ Logger.log(LogLevel.INFO, "starting audio thread...");
+ set_audio_pipeline_playing();
+
+ int perframe = (int) (ToxAV.DefaultCodecSettings.audio_frame_duration * ToxAV.DefaultCodecSettings.audio_sample_rate) / 1000;
+ int buffer_size;
+ int16[] buffer = new int16[perframe];
+ uint8[] enc_buffer = new uint8[perframe * 2];
+ ToxAV.AV_Error prep_frame_ret = 0, send_audio_ret = 0;
+
+ AudioCallInfo[] calls = new AudioCallInfo[MAX_CALLS];
+ int number_of_calls = 0;
+ bool preview = false;
+
+ bool running = true;
+ while (running) {
+ // calling try_pop once per cycle should be enough
+ AVStatusChange ? c = audio_status_changes.try_pop();
+ if (c != null) {
+ switch (c.type) {
+ case AudioStatusChangeType.START:
+ Logger.log(LogLevel.DEBUG, "Starting audio session %i".printf(c.call_index));
+ ToxAV.AV_Error e = toxav.prepare_transmission(
+ c.call_index,
+ ToxAV.JITTER_BUFFER_DEFAULT_CAPACITY,
+ ToxAV.VAD_DEFAULT_THRESHOLD,
+ c.var1 // video support
+ );
+ if (e != ToxAV.AV_Error.NONE) {
+ Logger.log(LogLevel.FATAL, "Could not prepare AV transmission: %s".printf(e.to_string()));
+ } else {
+ number_of_calls++;
+ calls[c.call_index].active = true;
+ }
+ break;
+ case AudioStatusChangeType.START_PREVIEW:
+ Logger.log(LogLevel.DEBUG, "Starting audio preview");
+ preview = true;
+ break;
+ case AudioStatusChangeType.END:
+ Logger.log(LogLevel.DEBUG, "Ending audio session %i".printf(c.call_index));
+ ToxAV.AV_Error e = toxav.kill_transmission(c.call_index);
+ if (e != ToxAV.AV_Error.NONE) {
+ Logger.log(LogLevel.FATAL, "Could not shutdown Audio transmission: %s".printf(e.to_string()));
+ } else {
+ number_of_calls--;
+ calls[c.call_index].active = false;
+ }
+ break;
+ case AudioStatusChangeType.END_PREVIEW:
+ Logger.log(LogLevel.DEBUG, "Ending audio preview");
+ preview = false;
+ break;
+ case AudioStatusChangeType.MUTE:
+ bool muted = (c.var1 == 1);
+ Logger.log(LogLevel.DEBUG, muted ? "Muting %i".printf(c.call_index) : "Unmuting %i".printf(c.call_index));
+ calls[c.call_index].muted = muted;
+ break;
+ case AudioStatusChangeType.VOLUME:
+ calls[c.call_index].volume = c.var1;
+ Logger.log(LogLevel.DEBUG, "Set receive volume for %i to %i".printf(c.call_index, c.var1));
+ //FIXME this only works for one contact right now
+ audio_volume_in.set("volume", ((double) c.var1) / 100.0);
+ break;
+ case AudioStatusChangeType.KILL:
+ Logger.log(LogLevel.DEBUG, "Audio thread received kill message");
+ running = false;
+ continue;
+ default:
+ Logger.log(LogLevel.ERROR, "unknown av status change type");
+ break;
+ }
+ }
+
+ // block until something gets pushed to audio_status_changes
+ if (number_of_calls == 0 && !preview) {
+ destroy_audio_pipeline();
+ c = audio_status_changes.pop();
+ audio_status_changes.push(c);
+ set_audio_pipeline_playing();
+ continue;
+ }
+
+ // read samples from pipeline
+ buffer_size = record_audio_buffer(ref buffer);
+
+ if (preview) {
+ play_audio_buffer(buffer, buffer_size);
+ }
+
+ // distribute samples across peers
+ for (int i = 0; i < MAX_CALLS; i++) {
+ if (calls[i].active) {
+ prep_frame_ret = toxav.prepare_audio_frame(i, enc_buffer, buffer, buffer_size);
+ if (prep_frame_ret <= 0) {
+ Logger.log(LogLevel.WARNING, "prepare_audio_frame returned an error: %s".printf(prep_frame_ret.to_string()));
+ } else {
+ send_audio_ret = toxav.send_audio(i, enc_buffer, prep_frame_ret);
+ if (send_audio_ret != ToxAV.AV_Error.NONE) {
+ Logger.log(LogLevel.WARNING, "send_audio returned %s".printf(send_audio_ret.to_string()));
+ }
+ }
+ }
+ }
+ }
+
+ Logger.log(LogLevel.INFO, "stopping audio thread...");
+ destroy_audio_pipeline();
+ return 0;
+ }
+
+ public int join() {
+ int ret = 0;
+ if (audio_thread != null) {
+ ret |= audio_thread.join();
+ }
+ if (video_thread != null) {
+ ret |= video_thread.join();
+ }
+ return ret;
+ }
+
+ // functions to control the AV Manager
+ public void set_volume(Contact c, int volume) {
+ audio_status_changes.push( AVStatusChange() {
+ type = AudioStatusChangeType.VOLUME,
+ call_index = c.call_index,
+ var1 = volume
+ });
+ }
+
+ public void set_mute(Contact c, bool mute) {
+ int imute = (mute ? 1 : 0);
+ audio_status_changes.push( AVStatusChange() {
+ type = AudioStatusChangeType.MUTE,
+ call_index = c.call_index,
+ var1 = imute
+ });
+ }
+
+ public void on_start_call(Contact c) {
+ int video = c.video ? 1 : 0;
+ audio_status_changes.push( AVStatusChange() {
+ type = AudioStatusChangeType.START,
+ call_index = c.call_index,
+ var1 = video
+ });
+
+ if (c.video) {
+ video_status_changes.push( AVStatusChange() {
+ type = VideoStatusChangeType.START,
+ call_index = c.call_index
+ });
+ }
+
+ if (audio_thread == null) {
+ audio_thread = new GLib.Thread("toxaudiothread", this.audio_thread_fun);
+ }
+
+ // start video thread on first video call
+ if (c.video && video_thread == null) {
+ video_thread = new Thread("toxvideothread", this.video_thread_fun);
+ }
+ }
+
+ public void on_end_call(Contact c) {
+ audio_status_changes.push( AVStatusChange() {
+ type = AudioStatusChangeType.END,
+ call_index = c.call_index
+ });
+
+ if (c.video) {
+ video_status_changes.push( AVStatusChange() {
+ type = VideoStatusChangeType.END,
+ call_index = c.call_index
+ });
+ }
+ }
+
+ public void start_audio_preview() {
+ audio_status_changes.push( AVStatusChange() {
+ type = AudioStatusChangeType.START_PREVIEW
+ });
+ if (audio_thread == null) {
+ audio_thread = new GLib.Thread("toxaudiothread", this.audio_thread_fun);
+ }
+ }
+
+ public void end_audio_preview() {
+ audio_status_changes.push( AVStatusChange() {
+ type = AudioStatusChangeType.END_PREVIEW
+ });
+ }
+
+ public void start_video_preview() {
+ video_status_changes.push( AVStatusChange() {
+ type = VideoStatusChangeType.START_PREVIEW
+ });
+ if (video_thread == null) {
+ video_thread = new Thread("toxvideothread", this.video_thread_fun);
+ }
+ }
+
+ public void end_video_preview() {
+ video_status_changes.push( AVStatusChange() {
+ type = VideoStatusChangeType.END_PREVIEW
+ });
+ }
+
+ public void play_sound(string location) {
+ Logger.log(LogLevel.DEBUG, "playing sound " + location);
+ Gst.Element playbin = Gst.ElementFactory.make("playbin2", "playbin");
+ Gst.Element sink = Gst.ElementFactory.make("autoaudiosink", "sink");
+ playbin.set("uri", location,
+ "audio-sink", sink);
+ Gst.Bus bus = ((Gst.Pipeline)playbin).get_bus();
+ bus.add_watch((bus, message) => {
+ Error e;
+ switch (message.type) {
+ case Gst.MessageType.ERROR:
+ message.parse_error(out e, null);
+ Logger.log(LogLevel.ERROR, "Error playing sound: " + e.message);
+ break;
+ case Gst.MessageType.EOS:
+ playbin.set_state(Gst.State.NULL);
+ playbin.unref();
+ Logger.log(LogLevel.DEBUG, "sound finished playing");
+ break;
+ case Gst.MessageType.WARNING:
+ message.parse_warning(out e, null);
+ Logger.log(LogLevel.WARNING, "Error playing sound: " + e.message);
+ break;
+ default:
+ break;
+ }
+ return true;
+ });
+ playbin.set_state(Gst.State.PLAYING);
+ }
+ }
+}
diff --git a/src/core/Application.vala b/src/core/Application.vala
new file mode 100644
index 0000000..060bc33
--- /dev/null
+++ b/src/core/Application.vala
@@ -0,0 +1,158 @@
+/*
+ * Application.vala
+ *
+ * Copyright (C) 2013-2018 Venom authors and contributors
+ *
+ * This file is part of Venom.
+ *
+ * Venom is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Venom is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Venom. If not, see .
+ */
+namespace Venom {
+ public class Application : Gtk.Application {
+ private const GLib.ActionEntry app_entries[] = {
+ { "preferences", on_show_preferences, null, null, null },
+ { "about", on_show_about, null, null, null },
+ { "quit", on_quit, null, null, null },
+ { "show-filetransfers", on_show_filetransfers, null, null, null },
+ { "show-contact", on_show_contact, "s", null, null }
+ };
+
+ private const OptionEntry[] option_entries = {
+ { "loglevel", 'l', 0, OptionArg.INT, ref loglevel, N_("Set level of messages to log"), N_("") },
+ { "version", 'V', 0, OptionArg.NONE, null, N_("Display version number"), null },
+ { null }
+ };
+
+ private static LogLevel loglevel = LogLevel.INFO;
+
+ private ApplicationWindow applicationWindow;
+ private IDatabase database;
+ private ILogger logger;
+ private IDhtNodeDatabase nodeDatabase;
+ private ISettingsDatabase settingsDatabase;
+ private IContactDatabase contact_database;
+ private Factory.IWidgetFactory widget_factory;
+ private IDatabaseFactory database_factory;
+
+ public Application() {
+ Object(
+ application_id: R.constants.app_id(),
+ flags: ApplicationFlags.HANDLES_OPEN
+ );
+ add_main_option_entries(option_entries);
+ add_action_entries(app_entries, this);
+ }
+
+ private ApplicationWindow getApplicationWindow() {
+ if (applicationWindow == null) {
+ applicationWindow = widget_factory.createApplicationWindow(this, nodeDatabase, settingsDatabase, contact_database);
+ }
+ return applicationWindow;
+ }
+
+ private static void create_path_for_filename(string filename) throws Error {
+ var path = GLib.File.new_for_path(GLib.Path.get_dirname(filename));
+ if (!path.query_exists()) {
+ path.make_directory_with_parents();
+ }
+ }
+
+ protected override void startup() {
+ base.startup();
+
+ Logger.displayed_level = loglevel;
+ widget_factory = new Factory.WidgetFactory();
+ logger = widget_factory.createLogger();
+ database_factory = widget_factory.createDatabaseFactory();
+
+ try {
+ var db_file = R.constants.db_filename();
+ create_path_for_filename(db_file);
+ database = database_factory.createDatabase(db_file);
+ var statementFactory = database_factory.createStatementFactory(database);
+ nodeDatabase = database_factory.createNodeDatabase(statementFactory, logger);
+ contact_database = database_factory.createContactDatabase(statementFactory, logger);
+ settingsDatabase = database_factory.createSettingsDatabase(statementFactory, logger);
+ settingsDatabase.load();
+
+ } catch (Error e) {
+ logger.f("Database creation failed: " + e.message);
+ assert_not_reached();
+ }
+
+ var builder = new Gtk.Builder();
+ try {
+ builder.add_from_resource("/chat/tox/venom/ui/app_menu.ui");
+ } catch (Error e) {
+ logger.f("Loading app menu failed: " + e.message);
+ assert_not_reached();
+ }
+
+ var app_menu = builder.get_object("app_menu") as MenuModel;
+ assert(app_menu != null);
+ set_app_menu(app_menu);
+ }
+
+ protected override void activate() {
+ hold();
+ getApplicationWindow().present();
+ release();
+ }
+
+ protected override int handle_local_options(GLib.VariantDict options) {
+ if (options.contains("version")) {
+ stdout.printf("%s %s\n", Environment.get_application_name(), Config.VERSION);
+ return 0;
+ }
+
+ return -1;
+ }
+
+ protected override void open(GLib.File[] files, string hint) {
+ logger.f("not implemented.");
+ }
+
+ private void on_show_preferences() {
+ getApplicationWindow().show_settings();
+ }
+
+ public void on_show_about() {
+ var about_dialog = widget_factory.createAboutDialog();
+ about_dialog.transient_for = getApplicationWindow();
+ about_dialog.run();
+ about_dialog.destroy();
+ }
+
+ public void on_show_contact(GLib.SimpleAction action, GLib.Variant? parameter) {
+ logger.d("on_show_contact");
+ activate();
+ if (parameter == null || parameter.get_string() == "") {
+ return;
+ }
+ getApplicationWindow().on_show_contact(parameter.get_string());
+ }
+
+ public void on_show_filetransfers() {
+ logger.i("on_show_filetransfers");
+ activate();
+ getApplicationWindow().on_filetransfer();
+ }
+
+ private void on_quit() {
+ if (applicationWindow != null) {
+ applicationWindow.destroy();
+ }
+ }
+ }
+}
diff --git a/src/core/Contact.vala b/src/core/Contact.vala
index d478c5d..be9e890 100644
--- a/src/core/Contact.vala
+++ b/src/core/Contact.vala
@@ -1,7 +1,7 @@
/*
* Contact.vala
*
- * Copyright (C) 2013-2014 Venom authors and contributors
+ * Copyright (C) 2013-2018 Venom authors and contributors
*
* This file is part of Venom.
*
@@ -19,116 +19,20 @@
* along with Venom. If not, see .
*/
-
namespace Venom {
- public interface IContact : GLib.Object {
+ public interface IContact : Object {
+ public signal void changed();
+
+ public abstract string get_id();
public abstract string get_name_string();
- public abstract string get_name_string_with_hyperlinks();
public abstract string get_status_string();
- public abstract string get_status_string_with_hyperlinks();
- public abstract string get_status_string_alt();
- public abstract string get_last_seen_string();
- public abstract string get_tooltip_string();
- }
-
- public class Contact : IContact, GLib.Object {
- // Saved in toxs savefile
- public uint8[] public_key { get; set; }
- public int friend_id { get; set; default = -1;}
- public string name { get; set; default = ""; }
- public string status_message { get; set; default = ""; }
- public DateTime last_seen { get; set; default = null; }
- public uint8 user_status { get; set; default = (uint8)Tox.UserStatus.INVALID; }
- // Saved in venoms savefile
- public string note { get; set; default = ""; }
- public string alias { get; set; default = ""; }
- public bool is_blocked { get; set; default = false; }
- public string group { get; set; default = ""; }
- // Not saved
- public bool online { get; set; default = false; }
- public Gdk.Pixbuf? image { get; set; default = null; }
- public int unread_messages { get; set; default = 0; }
- public bool is_typing { get; set; default = false; }
-
- private GLib.HashTable _file_transfers = new GLib.HashTable(null, null);
-
- public unowned GLib.HashTable get_filetransfers() {
- return _file_transfers;
- }
-
- public Contact(uint8[] public_key, int friend_id = -1) {
- this.public_key = public_key;
- this.friend_id = friend_id;
- }
-
- public string get_name_string() {
- if(name != "") {
- if(alias == "") {
- return name;
- } else {
- return _("%s (%s)").printf(Markup.escape_text(name), Markup.escape_text(alias));
- }
- } else if (alias != "") {
- return _("%s").printf(Markup.escape_text(alias));
- } else {
- return Tools.bin_to_hexstring(public_key);
- }
- }
-
- public string get_name_string_with_hyperlinks() {
- if(name != "") {
- if(alias == "") {
- return name;
- } else {
- return _("%s (%s)").printf(Tools.markup_uris(name), Tools.markup_uris(alias));
- }
- } else if (alias != "") {
- return _("%s").printf(Tools.markup_uris(alias));
- } else {
- return Tools.bin_to_hexstring(public_key);
- }
- }
-
- public string get_status_string() {
- if(online || status_message != "") {
- return Markup.escape_text(status_message);
- } else if (last_seen != null) {
- return get_last_seen_string();
- } else {
- return _("Offline");
- }
- }
-
- public string get_status_string_with_hyperlinks() {
- if(online || status_message != "") {
- return Tools.markup_uris(status_message);
- } else if (last_seen != null) {
- return get_last_seen_string();
- } else {
- return _("Offline");
- }
- }
-
- public string get_status_string_alt() {
- return Tools.markup_uris(status_message);
- }
-
- public string get_last_seen_string() {
- return last_seen != null ? _("Last seen: %s").printf(last_seen.format("%c")) : "";
- }
-
- public string get_tooltip_string() {
- StringBuilder b = new StringBuilder();
- b.append(get_name_string_with_hyperlinks());
- if(status_message != "") {
- b.append_c('\n');
- b.append(get_status_string_alt());
- }
- if(!online && last_seen != null) {
- b.append_c('\n');
- b.append(get_last_seen_string());
- }
- return b.str;
- }
+ public abstract UserStatus get_status();
+ public abstract bool is_connected();
+ public abstract bool is_typing();
+ public abstract bool is_conference();
+ public abstract Gdk.Pixbuf get_image();
+ public abstract bool get_requires_attention();
+ public abstract void clear_attention();
+ public abstract bool show_notifications();
}
}
diff --git a/src/core/ContactStorage.vala b/src/core/ContactStorage.vala
deleted file mode 100644
index d65369b..0000000
--- a/src/core/ContactStorage.vala
+++ /dev/null
@@ -1,117 +0,0 @@
-/*
- * ContactStorage.vala
- *
- * Copyright (C) 2013-2014 Venom authors and contributors
- *
- * This file is part of Venom.
- *
- * Venom is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * Venom is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with Venom. If not, see .
- */
-
-namespace Venom {
- public interface IContactStorage : GLib.Object {
- public abstract void load_contact_data(Contact c);
- public abstract void save_contact_data(Contact c);
- }
-
- public class SqliteContactStorage : IContactStorage, GLib.Object {
- private unowned Sqlite.Database db;
- private Sqlite.Statement insert_statement;
- private Sqlite.Statement select_statement;
- private static string QUERY_TABLE_CONTACTS = """
- CREATE TABLE IF NOT EXISTS Contacts (
- id INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL,
- key TEXT NOT NULL UNIQUE,
- note TEXT NOT NULL,
- alias TEXT NOT NULL,
- isblocked INTEGER DEFAULT 0,
- ingroup TEXT NOT NULL
- );
- """;
- private enum ContactColumn {
- ID,
- KEY,
- NOTE,
- ALIAS,
- ISBLOCKED,
- GROUP
- }
- private static string TABLE_KEY = "$KEY";
- private static string TABLE_NOTE = "$NOTE";
- private static string TABLE_ALIAS = "$ALIAS";
- private static string TABLE_ISBLOCKED = "$ISBLOCKED";
- private static string TABLE_GROUP = "$GROUP";
-
- private static string STATEMENT_INSERT_CONTACTS = "INSERT OR REPLACE INTO Contacts (key, note, alias, isblocked, ingroup) VALUES (%s, %s, %s, %s, %s);".printf(TABLE_KEY, TABLE_NOTE, TABLE_ALIAS, TABLE_ISBLOCKED, TABLE_GROUP);
- private static string STATEMENT_SELECT_CONTACTS = "SELECT * FROM Contacts WHERE key = %s".printf(TABLE_KEY);
-
- public void load_contact_data(Contact c) {
- string key = Tools.bin_to_hexstring(c.public_key);
-
- try {
- SqliteTools.put_text(select_statement, TABLE_KEY, key);
- } catch (SqliteStatementError e) {
- Logger.log(LogLevel.ERROR, "Error retrieving contact from sqlite database: " + e.message);
- return;
- }
-
- if(select_statement.step () == Sqlite.ROW) {
- c.note = select_statement.column_text(ContactColumn.NOTE);
- c.alias = select_statement.column_text(ContactColumn.ALIAS);
- c.is_blocked = select_statement.column_int (ContactColumn.ISBLOCKED) != 0;
- c.group = select_statement.column_text(ContactColumn.GROUP);
- }
-
- select_statement.reset ();
- }
- public void save_contact_data(Contact c) {
- string key = Tools.bin_to_hexstring(c.public_key);
-
- try {
- SqliteTools.put_text(insert_statement, TABLE_KEY, key);
- SqliteTools.put_text(insert_statement, TABLE_NOTE, c.note);
- SqliteTools.put_text(insert_statement, TABLE_ALIAS, c.alias);
- SqliteTools.put_int (insert_statement, TABLE_ISBLOCKED, c.is_blocked ? 1 : 0);
- SqliteTools.put_text(insert_statement, TABLE_GROUP, c.group);
- } catch (SqliteStatementError e) {
- Logger.log(LogLevel.ERROR, "Error writing contact to sqlite database: " + e.message);
- return;
- }
-
- insert_statement.step();
- insert_statement.reset();
- }
-
- public SqliteContactStorage( Sqlite.Database db ) throws SqliteDbError {
- this.db = db;
-
- string errmsg;
-
- //create table and index if needed
- if(db.exec (QUERY_TABLE_CONTACTS, null, out errmsg) != Sqlite.OK) {
- throw new SqliteDbError.QUERY(_("Error creating contacts table: %s\n"), errmsg);
- }
-
- //prepare insert statement for adding new history messages
- if(db.prepare_v2 (STATEMENT_INSERT_CONTACTS, STATEMENT_INSERT_CONTACTS.length, out insert_statement) != Sqlite.OK) {
- throw new SqliteDbError.QUERY(_("Error creating contacts insert statement: %d: %s\n"), db.errcode (), db.errmsg());
- }
-
- //prepare select statement to get history. Will execute on indexed data
- if(db.prepare_v2 (STATEMENT_SELECT_CONTACTS, STATEMENT_SELECT_CONTACTS.length, out select_statement) != Sqlite.OK) {
- throw new SqliteDbError.QUERY(_("Error creating contacts select statement: %d: %s\n"), db.errcode (), db.errmsg());
- }
- }
- }
-}
diff --git a/src/core/DhtNode.vala b/src/core/DhtNode.vala
deleted file mode 100644
index 9ec0dd0..0000000
--- a/src/core/DhtNode.vala
+++ /dev/null
@@ -1,50 +0,0 @@
-/*
- * DhtNode.vala
- *
- * Copyright (C) 2013-2014 Venom authors and contributors
- *
- * This file is part of Venom.
- *
- * Venom is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * Venom is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with Venom. If not, see .
- */
-
-using Tox;
-namespace Venom {
- public class DhtNode : GLib.Object {
- public string host {get; set;}
- public uint8[] pub_key {get; set;}
- public uint16 port {get; set;}
- public string maintainer {get; set;}
- public string location {get; set;}
- public bool is_blocked {get; set;}
-
- public bool is_ipv6 {get; private set;}
-
- public DhtNode.ipv4(string host, string pub_key, uint16 port = 33445, bool is_blocked = false, string maintainer = "", string location = "") {
- this.host = host;
- this.port = port;
- this.pub_key = Tools.hexstring_to_bin(pub_key);
- this.is_ipv6 = false;
- }
- public DhtNode.ipv6(string host, string pub_key, uint16 port = 33445, bool is_blocked = false, string maintainer = "", string location = "") {
- this.host = host;
- this.port = port;
- this.pub_key = Tools.hexstring_to_bin(pub_key);
- this.is_ipv6 = true;
- }
- public string to_string() {
- return "%s:%u%s %s".printf(host, port, is_ipv6 ? " (ipv6)" : "", Tools.bin_to_hexstring(pub_key));
- }
- }
-}
diff --git a/src/core/DhtNodeStorage.vala b/src/core/DhtNodeStorage.vala
deleted file mode 100644
index 13c20b2..0000000
--- a/src/core/DhtNodeStorage.vala
+++ /dev/null
@@ -1,186 +0,0 @@
-/*
- * DhtNodeStorage.vala
- *
- * Copyright (C) 2013-2014 Venom authors and contributors
- *
- * This file is part of Venom.
- *
- * Venom is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * Venom is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with Venom. If not, see .
- */
-
-namespace Venom {
-
- public interface IDhtNodeStorage : GLib.Object {
- public abstract DhtNode[] get_dht_nodes();
- public abstract void save_dht_node(DhtNode node);
- }
-
- public class DummyDhtNodeStorage : IDhtNodeStorage, GLib.Object {
- public DhtNode[] get_dht_nodes() {
- DhtNode[] nodes = {};
- nodes += new DhtNode.ipv4(
- "192.254.75.98",
- "951C88B7E75C867418ACDB5D273821372BB5BD652740BCDF623A4FA293E75D2F",
- 33445,
- false,
- "stqism",
- "US"
- );
- nodes += new DhtNode.ipv6(
- "2607:5600:284::2",
- "951C88B7E75C867418ACDB5D273821372BB5BD652740BCDF623A4FA293E75D2F",
- 33445,
- false,
- "stqism",
- "US"
- );
- nodes += new DhtNode.ipv4(
- "37.187.46.132",
- "A9D98212B3F972BD11DA52BEB0658C326FCCC1BFD49F347F9C2D3D8B61E1B927",
- 33445,
- false,
- "mouseym",
- "FR"
- );
- nodes += new DhtNode.ipv6(
- "2001:41d0:0052:0300::0507",
- "A9D98212B3F972BD11DA52BEB0658C326FCCC1BFD49F347F9C2D3D8B61E1B927",
- 33445,
- false,
- "mouseym",
- "FR"
- );
- nodes += new DhtNode.ipv4(
- "54.199.139.199",
- "7F9C31FE850E97CEFD4C4591DF93FC757C7C12549DDD55F8EEAECC34FE76C029",
- 33445,
- false,
- "aitjcize",
- "JP"
- );
- nodes += new DhtNode.ipv4(
- "109.169.46.133",
- "7F31BFC93B8E4016A902144D0B110C3EA97CB7D43F1C4D21BCAE998A7C838821",
- 33445,
- false,
- "astonex",
- "UK"
- );
- return nodes;
- }
- public void save_dht_node(DhtNode node) {}
- }
-
- public class SqliteDhtNodeStorage : IDhtNodeStorage, GLib.Object {
- private unowned Sqlite.Database db;
- private Sqlite.Statement insert_statement;
- private Sqlite.Statement select_statement;
- private static string QUERY_TABLE_NODES = """
- CREATE TABLE IF NOT EXISTS Nodes (
- id INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL,
- key TEXT NOT NULL,
- host TEXT NOT NULL,
- isipv6 INTEGER,
- port INTEGER,
- maintainer TEXT NOT NULL,
- location TEXT NOT NULL,
- isblocked INTEGER DEFAULT 0
- );
- """;
- private enum NodeColumn {
- ID,
- KEY,
- HOST,
- ISIPV6,
- PORT,
- MAINTAINER,
- LOCATION,
- ISBLOCKED
- }
- private static string TABLE_KEY = "$KEY";
- private static string TABLE_HOST = "$HOST";
- private static string TABLE_ISIPV6 = "$ISIPV6";
- private static string TABLE_PORT = "$PORT";
- private static string TABLE_MAINTAINER = "$MAINTAINER";
- private static string TABLE_LOCATION = "$LOCATION";
- private static string TABLE_ISBLOCKED = "$ISBLOCKED";
-
- private static string STATEMENT_INSERT_NODES = "INSERT INTO Nodes (key, host, isipv6, port, maintainer, location, isblocked) VALUES (%s, %s, %s, %s, %s, %s, %s);".printf(TABLE_KEY, TABLE_HOST, TABLE_ISIPV6, TABLE_PORT, TABLE_MAINTAINER, TABLE_LOCATION, TABLE_ISBLOCKED);
- private static string STATEMENT_SELECT_NODES = "SELECT * FROM Nodes";
-
- public DhtNode[] get_dht_nodes() {
- DhtNode[] nodes = {};
-
- while(select_statement.step () == Sqlite.ROW) {
- string key = select_statement.column_text(NodeColumn.KEY);
- string host = select_statement.column_text(NodeColumn.HOST);
- bool is_ipv6 = select_statement.column_int(NodeColumn.ISIPV6) != 0;
- uint16 port = (uint16) select_statement.column_int(NodeColumn.PORT);
- string maintainer = select_statement.column_text(NodeColumn.MAINTAINER);
- string location = select_statement.column_text(NodeColumn.LOCATION);
- bool is_blocked = select_statement.column_int(NodeColumn.ISBLOCKED) != 0;
-
- if(is_ipv6) {
- nodes += new DhtNode.ipv6(host, key, port, is_blocked, maintainer, location);
- } else {
- nodes += new DhtNode.ipv4(host, key, port, is_blocked, maintainer, location);
- }
- }
-
- select_statement.reset ();
- return nodes;
- }
-
- public void save_dht_node(DhtNode node) {
- string key = Tools.bin_to_hexstring(node.pub_key);
-
- try {
- SqliteTools.put_text(insert_statement, TABLE_KEY, key);
- SqliteTools.put_text(insert_statement, TABLE_HOST, node.host);
- SqliteTools.put_int (insert_statement, TABLE_ISIPV6, node.is_ipv6 ? 1 : 0);
- SqliteTools.put_int (insert_statement, TABLE_PORT, node.port);
- SqliteTools.put_text(insert_statement, TABLE_MAINTAINER, node.maintainer);
- SqliteTools.put_text(insert_statement, TABLE_LOCATION, node.location);
- SqliteTools.put_int (insert_statement, TABLE_ISBLOCKED, node.is_blocked ? 1 : 0);
- } catch (SqliteStatementError e) {
- Logger.log(LogLevel.ERROR, "Error writing dht node to sqlite database: " + e.message);
- return;
- }
-
- insert_statement.step();
- insert_statement.reset();
- }
-
- public SqliteDhtNodeStorage( Sqlite.Database db ) throws SqliteDbError {
- this.db = db;
-
- string errmsg;
-
- //create table and index if needed
- if(db.exec (QUERY_TABLE_NODES, null, out errmsg) != Sqlite.OK) {
- throw new SqliteDbError.QUERY(_("Error creating dht nodes table: %s\n"), errmsg);
- }
-
- //prepare insert statement for adding new history messages
- if(db.prepare_v2 (STATEMENT_INSERT_NODES, STATEMENT_INSERT_NODES.length, out insert_statement) != Sqlite.OK) {
- throw new SqliteDbError.QUERY(_("Error creating dht nodes insert statement: %d: %s\n"), db.errcode (), db.errmsg());
- }
-
- //prepare select statement to get history. Will execute on indexed data
- if(db.prepare_v2 (STATEMENT_SELECT_NODES, STATEMENT_SELECT_NODES.length, out select_statement) != Sqlite.OK) {
- throw new SqliteDbError.QUERY(_("Error creating dht nodes select statement: %d: %s\n"), db.errcode (), db.errmsg());
- }
- }
- }
-}
diff --git a/src/core/FileIO.vala b/src/core/FileIO.vala
new file mode 100644
index 0000000..587d763
--- /dev/null
+++ b/src/core/FileIO.vala
@@ -0,0 +1,38 @@
+/*
+ * FileIO.vala
+ *
+ * Copyright (C) 2018 Venom authors and contributors
+ *
+ * This file is part of Venom.
+ *
+ * Venom is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Venom is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Venom. If not, see .
+ */
+
+namespace Venom {
+ public class FileIO : GLib.Object {
+ private FileIO() {}
+
+ public static string? load_contents_text(string path) throws Error {
+ var file = File.new_for_path(path);
+ uint8[] buf;
+ file.load_contents(null, out buf, null);
+ return (string) buf;
+ }
+
+ public static void save_contents_text(string path, string data) throws Error {
+ var file = File.new_for_path(path);
+ file.replace_contents(data.data, null, false, FileCreateFlags.NONE, null, null);
+ }
+ }
+}
diff --git a/src/core/FileTransfer.vala b/src/core/FileTransfer.vala
index 3e8d359..d970e81 100644
--- a/src/core/FileTransfer.vala
+++ b/src/core/FileTransfer.vala
@@ -1,7 +1,7 @@
/*
* FileTransfer.vala
*
- * Copyright (C) 2013-2014 Venom authors and contributors
+ * Copyright (C) 2018 Venom authors and contributors
*
* This file is part of Venom.
*
@@ -20,92 +20,204 @@
*/
namespace Venom {
+ public enum FileTransferState {
+ INIT,
+ PAUSED,
+ RUNNING,
+ CANCEL,
+ FINISHED,
+ FAILED
+ }
+
public enum FileTransferDirection {
- OUTGOING,
- INCOMING
+ INCOMING,
+ OUTGOING
}
- public enum FileTransferStatus {
- PENDING,
- SENDING_FAILED,
- RECEIVING_FAILED,
- SENDING_BROKEN,
- RECEIVING_BROKEN,
- REJECTED,
- IN_PROGRESS,
- PAUSED,
- CANCELED,
- DONE
+
+ public errordomain FileTransferError {
+ READ,
+ WRITE,
+ INIT,
+ OVERFLOW
}
- public class FileTransfer : GLib.Object {
- public signal void status_changed(FileTransferStatus status, FileTransferDirection direction);
- public signal void progress_update(uint64 processed, uint64 filesize);
-
- public Contact friend {get; set; }
- public uint8 filenumber {get; set; }
- private FileTransferStatus _status;
- public FileTransferStatus status {
- get { return _status; }
- set {
- _status = value;
- status_changed(_status, direction);
+ public interface FileTransfer : GLib.Object {
+ public signal void state_changed();
+ public signal void progress_changed();
+
+ public abstract FileTransferDirection get_direction();
+ public abstract uint32 get_friend_number();
+ public abstract uint32 get_file_number();
+ public abstract uint64 get_file_size();
+ public abstract uint64 get_transmitted_size();
+ public abstract FileTransferState get_state();
+ public abstract bool is_avatar();
+ public abstract unowned uint8[] ? get_avatar_buffer();
+
+ public abstract void init_file(File file) throws Error;
+
+ public abstract void write_data(uint8[] data) throws Error;
+ public abstract uint8[] read_data(uint64 length) throws Error;
+
+ public abstract string? get_file_name();
+ public abstract string? get_file_path();
+ public abstract void set_state(FileTransferState state);
+ }
+
+ public class FileTransferImpl : FileTransfer, GLib.Object {
+ private FileTransferDirection direction;
+ private uint32 friend_number;
+ private uint32 file_number;
+ private uint64 file_size;
+ private uint64 transmitted_size;
+ private FileTransferState state;
+
+ private bool _is_avatar;
+ private uint8[] avatar_buffer;
+
+ private string file_name;
+ private File file;
+
+ private FileTransferImpl(FileTransferDirection direction, uint32 friend_number, uint32 file_number, uint64 file_size) {
+ this.friend_number = friend_number;
+ this.file_number = file_number;
+ this.direction = direction;
+ this.file_size = file_size;
+
+ state = FileTransferState.INIT;
+ transmitted_size = 0;
+ }
+
+ public FileTransferImpl.File(FileTransferDirection direction, uint32 friend_number, uint32 file_number, uint64 file_size, string file_name) {
+ this(direction, friend_number, file_number, file_size);
+ this.file_name = file_name;
+ _is_avatar = false;
+ }
+
+ public FileTransferImpl.Avatar(FileTransferDirection direction, uint32 friend_number, uint32 file_number, uint64 file_size) {
+ this(direction, friend_number, file_number, file_size);
+ avatar_buffer = new uint8[file_size];
+ _is_avatar = true;
+ }
+
+ public FileTransferImpl.AvatarOutgoing(FileTransferDirection direction, uint32 friend_number, uint32 file_number, uint8[] buffer) {
+ this(direction, friend_number, file_number, buffer.length);
+ avatar_buffer = buffer;
+ _is_avatar = true;
+ }
+
+ public void init_file(File file) throws Error {
+ this.file = file;
+ if (direction == INCOMING) {
+ file.replace(null, false, GLib.FileCreateFlags.NONE);
+ }
+ }
+
+ private static void copy_with_offset(uint8[] dest, uint8[] src, uint64 offset) {
+ unowned uint8[] dest_ptr = dest[offset : dest.length];
+ GLib.Memory.copy(dest_ptr, src, src.length);
+ }
+
+ public bool is_avatar() {
+ return _is_avatar;
+ }
+
+ public uint64 get_transmitted_size() {
+ return transmitted_size;
+ }
+
+ public uint64 get_file_size() {
+ return file_size;
+ }
+
+ public void write_data(uint8[] data) throws Error {
+ if (data.length + transmitted_size > file_size) {
+ set_state(FileTransferState.FAILED);
+ throw new FileTransferError.OVERFLOW("Appending too much data, discarding data");
+ }
+
+ if (_is_avatar) {
+ copy_with_offset(avatar_buffer, data, transmitted_size);
+ } else {
+ if (file == null) {
+ set_state(FileTransferState.FAILED);
+ throw new FileTransferError.INIT("File is not initialized");
+ }
+ try {
+ file.append_to(GLib.FileCreateFlags.NONE).write(data);
+ } catch (Error e) {
+ set_state(FileTransferState.FAILED);
+ throw new FileTransferError.WRITE("Writing to file failed: " + e.message);
+ }
}
+
+ transmitted_size += data.length;
+ progress_changed();
}
- public uint8 send_receive { get; set; }
- public FileTransferDirection direction {get; set;}
- public uint64 file_size { get; set; }
- /* amount of bytes sent or received during transfer */
- public uint64 _bytes_processed;
- public uint64 bytes_processed {
- get { return _bytes_processed; }
- set {
- progress_update(value,file_size);
- _bytes_processed = value;
+ public uint8[] read_data(uint64 length) throws Error {
+ if (length + transmitted_size > file_size) {
+ set_state(FileTransferState.FAILED);
+ throw new FileTransferError.OVERFLOW("Appending too much data, discarding data");
+ }
+ var buf = new uint8[length];
+ if (_is_avatar) {
+ unowned uint8[] offset_ptr = avatar_buffer[transmitted_size : avatar_buffer.length];
+ GLib.Memory.copy(buf, offset_ptr, buf.length);
+ } else {
+ if (file == null) {
+ set_state(FileTransferState.FAILED);
+ throw new FileTransferError.INIT("File is not initialized");
+ }
+ try {
+ var istream = file.read();
+ istream.seek((int64) transmitted_size, SeekType.SET);
+ istream.read(buf);
+ } catch (Error e) {
+ set_state(FileTransferState.FAILED);
+ throw new FileTransferError.WRITE("Writing to file failed: " + e.message);
+ }
}
+
+ transmitted_size += length;
+ progress_changed();
+ return buf;
}
- public bool isfile { get; set; }
- public uint8[] data { get; set; }
- public string name { get; set; }
- public string path { get; set; }
- public DateTime time_sent { get; set; }
- public FileTransfer(Contact friend, FileTransferDirection send_receive, uint64 file_size, string name, string? path) {
- this.friend = friend;
- this.direction = send_receive;
- this.send_receive = send_receive;
- this.file_size = file_size;
- this.name = name;
- this.isfile = true;
- this.path = path;
- this.time_sent = new DateTime.now_local();
- this.status = FileTransferStatus.PENDING;
- this.bytes_processed = 0;
- }
-
- public FileTransfer.senddata(Contact friend, string name, uint8[] data) {
- this.friend = friend;
- this.direction = FileTransferDirection.OUTGOING;
- this.send_receive = 0;
- this.file_size = data.length;
- this.name = name;
- this.isfile = false;
- this.data = data;
- this.time_sent = new DateTime.now_local();
- this.status = FileTransferStatus.PENDING;
- this.bytes_processed = 0;
- }
-
- public FileTransfer.recvdata(Contact friend, string name, uint64 file_size) {
- this.friend = friend;
- this.direction = FileTransferDirection.INCOMING;
- this.send_receive = 1;
- this.file_size = file_size;
- this.name = name;
- this.isfile = false;
- this.data = {};
- this.time_sent = new DateTime.now_local();
- this.status = FileTransferStatus.PENDING;
- this.bytes_processed = 0;
+
+ public unowned uint8[] ? get_avatar_buffer() {
+ return avatar_buffer;
+ }
+
+ public FileTransferState get_state() {
+ return state;
+ }
+
+ public void set_state(FileTransferState state) {
+ this.state = state;
+ state_changed();
+ }
+
+ public uint32 get_friend_number() {
+ return friend_number;
+ }
+
+ public uint32 get_file_number() {
+ return file_number;
+ }
+
+ public FileTransferDirection get_direction() {
+ return direction;
+ }
+
+ public string? get_file_name() {
+ return file_name;
+ }
+
+ public string? get_file_path() {
+ if (file == null) {
+ return null;
+ }
+ return file.get_path();
}
}
}
diff --git a/src/core/GroupChat.vala b/src/core/GroupChat.vala
deleted file mode 100644
index 58347e6..0000000
--- a/src/core/GroupChat.vala
+++ /dev/null
@@ -1,76 +0,0 @@
-/*
- * GroupChat.vala
- *
- * Copyright (C) 2013-2014 Venom authors and contributors
- *
- * This file is part of Venom.
- *
- * Venom is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * Venom is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with Venom. If not, see .
- */
-
-namespace Venom {
- public class GroupChat : IContact, GLib.Object{
-
- public uint8[] public_key { get; set; default = null; }
- public int group_id { get; set; default = -1; }
- public string local_name { get; set; default = ""; }
- public Gdk.Pixbuf? image { get; set; default = null; }
- public int peer_count { get; set; default = 0; }
- public int unread_messages { get; set; default = 0; }
- public GLib.HashTable peers
- { get; set; }
-
- public GroupChat(uint8[] public_key, int group_id = -1) {
- this.public_key = public_key;
- this.group_id = group_id;
- this.peers = new GLib.HashTable(null, null);
- }
- public GroupChat.from_id(int group_id) {
- this.group_id = group_id;
- this.peers = new GLib.HashTable(null, null);
- }
-
- public string get_name_string() {
- return local_name == "" ? _("Groupchat #%i").printf(group_id) : Markup.escape_text(local_name);
- }
- public string get_name_string_with_hyperlinks() {
- return get_name_string();
- }
- public string get_status_string() {
- if(peer_count > 1) {
- return _("%i people connected").printf(peer_count);
- } else if(peer_count > 0) {
- return _("%i person connected").printf(peer_count);
- } else {
- return _("no one connected");
- }
- }
- public string get_status_string_with_hyperlinks() {
- return get_status_string();
- }
- public string get_status_string_alt() {
- return get_status_string();
- }
- public string get_last_seen_string() {
- return "";
- }
- public string get_tooltip_string() {
- StringBuilder b = new StringBuilder();
- b.append(get_name_string_with_hyperlinks());
- b.append_c('\n');
- b.append(get_status_string_alt());
- return b.str;
- }
- }
-}
diff --git a/src/core/GroupChatContact.vala b/src/core/GroupChatContact.vala
deleted file mode 100644
index d7e849d..0000000
--- a/src/core/GroupChatContact.vala
+++ /dev/null
@@ -1,56 +0,0 @@
-/*
- * GroupChatContact.vala
- *
- * Copyright (C) 2013-2014 Venom authors and contributors
- *
- * This file is part of Venom.
- *
- * Venom is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * Venom is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with Venom. If not, see .
- */
-
-namespace Venom {
- public class GroupChatContact : IContact, GLib.Object{
- public int group_contact_id { get; set; }
- public string name { get; set; }
-
- public GroupChatContact(int group_contact_id, string? name = null) {
- this.group_contact_id = group_contact_id;
- this.name = name;
- }
-
- public string get_status_string() { return _("Online"); }
- public string get_status_string_with_hyperlinks() { return get_status_string(); }
- public string get_status_string_alt() { return get_status_string(); }
- public string get_last_seen_string() { return ""; }
-
- public string get_name_string() {
- if(name != null && name != "") {
- return Markup.escape_text(name);
- } else {
- return "<unknown>";
- }
- }
-
- public string get_name_string_with_hyperlinks() {
- if(name != null && name != "") {
- return Tools.markup_uris(name);
- } else {
- return "<unknown>";
- }
- }
- public string get_tooltip_string() {
- return get_name_string();
- }
- }
-}
diff --git a/src/core/Interfaces.vala b/src/core/Interfaces.vala
new file mode 100644
index 0000000..1e2d74a
--- /dev/null
+++ b/src/core/Interfaces.vala
@@ -0,0 +1,50 @@
+/*
+ * Interfaces.vala
+ *
+ * Copyright (C) 2017-2018 Venom authors and contributors
+ *
+ * This file is part of Venom.
+ *
+ * Venom is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Venom is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Venom. If not, see .
+ */
+
+namespace Venom {
+ public interface IDhtNode : Object {
+ public abstract string pub_key { get; set; }
+ public abstract string host { get; set; }
+ public abstract uint port { get; set; }
+ public abstract string maintainer { get; set; }
+ public abstract string location { get; set; }
+ public abstract bool is_blocked { get; set; }
+
+ public string to_string() {
+ return "%s:%u %s - %s / %s (blocked: %s)".printf(host, port, pub_key, maintainer, location, is_blocked ? "true" : "false");
+ }
+ }
+
+ public interface ILogger : Object {
+ public abstract void d(string message);
+ public abstract void i(string message);
+ public abstract void w(string message);
+ public abstract void e(string message);
+ public abstract void f(string message);
+ public abstract void attach_to_glib();
+ }
+
+ public enum UserStatus {
+ NONE,
+ AWAY,
+ BUSY
+ }
+}
diff --git a/src/core/Logger.vala b/src/core/Logger.vala
index 47b5485..a24254d 100644
--- a/src/core/Logger.vala
+++ b/src/core/Logger.vala
@@ -1,7 +1,7 @@
/*
* Logger.vala
*
- * Copyright (C) 2013-2014 Venom authors and contributors
+ * Copyright (C) 2013-2018 Venom authors and contributors
*
* This file is part of Venom.
*
@@ -20,6 +20,24 @@
*/
namespace Venom {
+ namespace TermColor {
+ public const string BLACK = "\x1B[30m";
+ public const string RED = "\x1B[31m";
+ public const string GREEN = "\x1B[32m";
+ public const string YELLOW = "\x1B[33m";
+ public const string BLUE = "\x1B[34m";
+ public const string MAGENTA = "\x1B[35m";
+ public const string CYAN = "\x1B[36m";
+ public const string WHITE = "\x1B[37m";
+
+ public const string RESET = "\x1B[0m";
+
+ public const string INFO = TermColor.GREEN;
+ public const string WARNING = TermColor.YELLOW;
+ public const string ERROR = TermColor.RED;
+ public const string FATAL = TermColor.MAGENTA;
+ }
+
public enum LogLevel {
DEBUG,
INFO,
@@ -28,26 +46,92 @@ namespace Venom {
FATAL;
public string to_string() {
- switch(this) {
+ switch (this) {
case DEBUG:
- return "DBG";
+ return "DEBUG";
case INFO:
- return "INFO";
+ return TermColor.INFO + "INFO " + TermColor.RESET;
case WARNING:
- return "WARN";
+ return TermColor.WARNING + "WARN " + TermColor.RESET;
case ERROR:
- return "ERROR";
+ return TermColor.ERROR + "ERROR" + TermColor.RESET;
case FATAL:
- return "FATAL";
+ return TermColor.FATAL + "FATAL" + TermColor.RESET;
default:
- return "UNKOWN";
+ assert_not_reached();
}
}
}
- public class Logger : GLib.Object {
- public static LogLevel displayed_level {get; set; default = LogLevel.WARNING;}
+
+ public class Logger : ILogger, Object {
+ public static LogLevel displayed_level { get; set; default = LogLevel.WARNING; }
+
+ public Logger() {
+ d("Logger created.");
+ }
+
+ ~Logger() {
+ d("Logger destroyed.");
+ }
+
+ public void d(string message) {
+ log(LogLevel.DEBUG, message);
+ }
+
+ public void i(string message) {
+ log(LogLevel.INFO, message);
+ }
+
+ public void w(string message) {
+ log(LogLevel.WARNING, message);
+ }
+
+ public void e(string message) {
+ log(LogLevel.ERROR, message);
+ }
+
+ public void f(string message) {
+ log(LogLevel.FATAL, message);
+ }
+
+ private void glib_log_function(string? log_domain, LogLevelFlags log_levels, string message) {
+ string concatMessage = log_domain != null
+ ? log_domain + " : " + message
+ : message;
+ switch (log_levels) {
+ case LogLevelFlags.FLAG_FATAL:
+ case LogLevelFlags.LEVEL_CRITICAL:
+ f(concatMessage);
+ break;
+ case LogLevelFlags.LEVEL_ERROR:
+ e(concatMessage);
+ break;
+ case LogLevelFlags.LEVEL_WARNING:
+ w(concatMessage);
+ break;
+ case LogLevelFlags.LEVEL_INFO:
+ i(concatMessage);
+ break;
+ case LogLevelFlags.LEVEL_DEBUG:
+ d(concatMessage);
+ break;
+ default:
+ w(concatMessage);
+ break;
+ }
+ }
+
+ public void attach_to_glib() {
+ //GLib.Log.set_default_handler(glib_log_function);
+ GLib.Log.set_handler(null, LogLevelFlags.LEVEL_MASK, glib_log_function);
+ GLib.Log.set_handler("GLib", LogLevelFlags.LEVEL_MASK, glib_log_function);
+ GLib.Log.set_handler("GLib-GObject", LogLevelFlags.LEVEL_MASK, glib_log_function);
+ GLib.Log.set_handler("Gdk", LogLevelFlags.LEVEL_MASK, glib_log_function);
+ GLib.Log.set_handler("Json", LogLevelFlags.LEVEL_MASK, glib_log_function);
+ }
+
public static void log(LogLevel level, string message) {
- if(level < displayed_level) {
+ if (level < displayed_level) {
return;
}
unowned FileStream s = level < LogLevel.ERROR ? stdout : stderr;
diff --git a/src/core/Message.vala b/src/core/Message.vala
index 178d767..32794f1 100644
--- a/src/core/Message.vala
+++ b/src/core/Message.vala
@@ -1,7 +1,7 @@
/*
* Message.vala
*
- * Copyright (C) 2013-2014 Venom authors and contributors
+ * Copyright (C) 2013-2018 Venom authors and contributors
*
* This file is part of Venom.
*
@@ -24,196 +24,90 @@ namespace Venom {
INCOMING,
OUTGOING
}
- public interface IMessage : GLib.Object {
- public abstract DateTime timestamp {get; protected set;}
- public abstract MessageDirection message_direction {get; protected set;}
- public abstract bool important {get; set;}
- public abstract bool is_action {get; set;}
-
- /*
- * Get plain sender string
- */
- public abstract string get_sender_plain();
- /*
- * Get plain message string
- */
+ public interface IMessage : Object {
+ public signal void message_changed();
+
+ public abstract DateTime timestamp { get; protected set; }
+ public abstract MessageDirection message_direction { get; protected set; }
+ public abstract bool important { get; set; }
+ public abstract bool is_action { get; set; }
+ public abstract bool received { get; set; }
+
+ public abstract string get_sender_plain();
+ public abstract string get_sender_id();
+ public abstract string get_conversation_id();
public abstract string get_message_plain();
+ public abstract string get_time_plain();
- /*
- * Get plain time string
- */
- public virtual string get_time_plain() {
- return timestamp.format(_("%R:%S"));
- }
+ public abstract bool is_conference_message();
- public abstract string get_notification_header();
public abstract Gdk.Pixbuf get_sender_image();
-
- /*
- * Compare this senders of two messages
- */
- public abstract bool compare_sender(IMessage to);
+ public abstract bool equals_sender(IMessage m);
}
- public class Message : IMessage, GLib.Object {
- public unowned Contact from {get; protected set;}
- public unowned Contact to {get; protected set;}
- public string message {get; protected set;}
- public DateTime timestamp {get; protected set;}
- public MessageDirection message_direction {get; protected set;}
- public bool important {get; set; default = false;}
- public bool is_action {get; set; default = false;}
-
- public Message.outgoing(Contact receiver, string message, DateTime timestamp = new DateTime.now_local()) {
+
+ public class Message : IMessage, ILoggedMessage, Object {
+ public GLib.DateTime timestamp { get; protected set; }
+ public MessageDirection message_direction { get; protected set; }
+ public bool important { get; set; default = false; }
+ public bool is_action { get; set; default = false; }
+ public bool received { get; set; }
+
+ public unowned IContact from { get; protected set; }
+ public unowned IContact to { get; protected set; }
+ public string message { get; protected set; }
+ public uint32 message_id { get; set; }
+
+ public Message.outgoing(IContact receiver, string message, GLib.DateTime timestamp = new GLib.DateTime.now_local()) {
this.message_direction = MessageDirection.OUTGOING;
this.from = null;
this.to = receiver;
this.message = message;
this.timestamp = timestamp;
}
- public Message.incoming(Contact sender, string message, DateTime timestamp = new DateTime.now_local()) {
+
+ public Message.incoming(IContact sender, string message, GLib.DateTime timestamp = new GLib.DateTime.now_local()) {
this.message_direction = MessageDirection.INCOMING;
this.from = sender;
this.to = null;
this.message = message;
this.timestamp = timestamp;
}
- public virtual string get_sender_plain() {
- if(from == null) {
- return User.instance.name;
+
+ public string get_sender_plain() {
+ if (from == null) {
+ return _("me");
} else {
- return from.name;
+ return from.get_name_string();
}
}
- public virtual string get_message_plain() {
- return message;
- }
- public virtual string get_notification_header() {
- return get_sender_plain() + _(" says:");
- }
- public Gdk.Pixbuf get_sender_image() {
- return from.image ?? ResourceFactory.instance.default_contact;
- }
- public bool compare_sender(IMessage to) {
- if(to is Message) {
- return (from == (to as Message).from);
- }
- return false;
- }
- }
- public class ActionMessage : Message {
- public ActionMessage.outgoing(Contact receiver, string message, DateTime timestamp = new DateTime.now_local()) {
- this.message_direction = MessageDirection.OUTGOING;
- this.from = null;
- this.to = receiver;
- this.message = message;
- this.timestamp = timestamp;
- this.is_action = true;
- }
- public ActionMessage.incoming(Contact sender, string message, DateTime timestamp = new DateTime.now_local()) {
- this.message_direction = MessageDirection.INCOMING;
- this.from = sender;
- this.to = null;
- this.message = message;
- this.timestamp = timestamp;
- this.is_action = true;
- }
- public override string get_sender_plain() {
- return "*";
- }
- public override string get_message_plain() {
- return "%s %s".printf(message_direction == MessageDirection.INCOMING ? from.name : User.instance.name, message);
- }
- public override string get_notification_header() {
- return from.get_name_string() + ":";
- }
- }
- public class GroupMessage : IMessage, GLib.Object {
- public unowned GroupChat from {get; protected set;}
- public unowned GroupChat to {get; protected set;}
- public GroupChatContact from_contact {get; protected set;}
- public string message {get; protected set;}
- public DateTime timestamp {get; protected set;}
- public MessageDirection message_direction {get; protected set;}
- public bool important {get; set; default = false;}
- public bool is_action {get; set; default = false;}
-
- public GroupMessage.outgoing(GroupChat receiver, string message, DateTime timestamp = new DateTime.now_local()) {
- this.message_direction = MessageDirection.OUTGOING;
- this.from = null;
- this.to = receiver;
- this.from_contact = null;
- this.message = message;
- this.timestamp = timestamp;
- }
- public GroupMessage.incoming(GroupChat sender, GroupChatContact from_contact, string message, DateTime timestamp = new DateTime.now_local()) {
- this.message_direction = MessageDirection.INCOMING;
- this.from = sender;
- this.to = null;
- this.from_contact = from_contact;
- this.message = message;
- this.timestamp = timestamp;
+
+ public string get_sender_id() {
+ return (from == null) ? to.get_id() : from.get_id();
}
- public virtual string get_sender_plain() {
- if(from == null) {
- return User.instance.name;
- } else {
- if(this.message_direction == MessageDirection.OUTGOING) {
- return User.instance.name;
- }
- return from_contact.name != null ? from_contact.name : _("");
- }
+
+ public string get_conversation_id() {
+ return get_sender_id();
}
- public virtual string get_message_plain() {
+
+ public string get_message_plain() {
return message;
}
- public virtual string get_notification_header() {
- return from_contact.get_name_string() + _(" in ") + from.get_name_string() + _(" says:");
- }
- public Gdk.Pixbuf get_sender_image() {
- return from.image ?? ResourceFactory.instance.default_groupchat;
+
+ public string get_time_plain() {
+ return timestamp.format("%c");
}
- public bool compare_sender(IMessage to) {
- if(to is GroupMessage) {
- GroupMessage gm = to as GroupMessage;
- return ((from == gm.from) && (from_contact == gm.from_contact));
- }
+
+ public bool is_conference_message() {
return false;
}
- }
- public class GroupActionMessage : GroupMessage {
- public GroupActionMessage.outgoing(GroupChat receiver, string message, DateTime timestamp = new DateTime.now_local()) {
- this.message_direction = MessageDirection.OUTGOING;
- this.from = null;
- this.to = receiver;
- this.from_contact = from_contact;
- this.message = message;
- this.timestamp = timestamp;
- this.is_action = true;
- }
- public GroupActionMessage.incoming(GroupChat sender, GroupChatContact from_contact, string message, DateTime timestamp = new DateTime.now_local()) {
- this.message_direction = MessageDirection.INCOMING;
- this.from = sender;
- this.to = null;
- this.from_contact = from_contact;
- this.message = message;
- this.timestamp = timestamp;
- this.is_action = true;
- }
- public override string get_sender_plain() {
- return "*";
- }
- public override string get_message_plain() {
- string name_string;
- if(message_direction == MessageDirection.INCOMING) {
- name_string = from_contact.name != null ? from_contact.name : _("");
- } else {
- name_string = User.instance.name;
- }
- return "%s %s".printf(message_direction == MessageDirection.INCOMING ? from_contact.name : User.instance.name, message);
+
+ public Gdk.Pixbuf get_sender_image() {
+ return from != null ? from.get_image() : pixbuf_from_resource(R.icons.default_contact);
}
- public override string get_notification_header() {
- return from_contact.get_name_string() + _(" in ") + from.get_name_string() + ":";
+
+ public bool equals_sender(IMessage m) {
+ return m is Message && from == (m as Message).from;
}
}
}
diff --git a/src/core/MessageLog.vala b/src/core/MessageLog.vala
deleted file mode 100644
index 1ef0c39..0000000
--- a/src/core/MessageLog.vala
+++ /dev/null
@@ -1,200 +0,0 @@
-/*
- * LocalStorage.vala
- *
- * Copyright (C) 2013-2014 Venom authors and contributors
- *
- * This file is part of Venom.
- *
- * Venom is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * Venom is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with Venom. If not, see .
- */
-
-namespace Venom {
- public interface IMessageLog : GLib.Object {
- public abstract string myId {get; set;}
- public abstract void on_message(Contact c, string message, bool issender);
- public abstract GLib.List? retrieve_history(Contact c);
- public abstract void sanitize_database();
- public abstract void connect_to(ToxSession session);
- public abstract void disconnect_from(ToxSession session);
- }
-
- public class DummyMessageLog : IMessageLog, GLib.Object {
- public string myId {get; set;}
- public void on_message(Contact c, string message, bool issender) {}
- public GLib.List? retrieve_history(Contact c) { return null; }
- public void sanitize_database() {}
- public void connect_to(ToxSession session) {}
- public void disconnect_from(ToxSession session) {}
- }
-
-
- public class SqliteMessageLog : IMessageLog, GLib.Object {
- public string myId {get; set;}
-
- public enum HistoryColumn {
- ID,
- USER,
- CONTACT,
- MESSAGE,
- TIME,
- SENDER
- }
-
- private unowned Sqlite.Database db;
- private Sqlite.Statement insert_statement;
- private Sqlite.Statement select_statement;
- private Sqlite.Statement delete_statement;
-
- private static string TABLE_USER = "$USER";
- private static string TABLE_CONTACT = "$CONTACT";
- private static string TABLE_MESSAGE = "$MESSAGE";
- private static string TABLE_TIME = "$TIME";
- private static string TABLE_SENDER = "$SENDER";
-
- private static string STATEMENT_INSERT_HISTORY = "INSERT INTO History (userHash, contactHash, message, timestamp, issent) VALUES (%s, %s, %s, %s, %s);".printf(TABLE_USER, TABLE_CONTACT, TABLE_MESSAGE, TABLE_TIME, TABLE_SENDER);
- private static string STATEMENT_SELECT_HISTORY = "SELECT * FROM History WHERE userHash = %s AND contactHash = %s;".printf(TABLE_USER, TABLE_CONTACT);
- private static string STATEMENT_SANITIZE_DATABASE = "DELETE FROM History WHERE timestamp < %s;".printf(TABLE_TIME);
-
- private static string QUERY_TABLE_HISTORY = """
- CREATE TABLE IF NOT EXISTS History (
- id INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL,
- userHash TEXT NOT NULL,
- contactHash TEXT NOT NULL,
- message TEXT NOT NULL,
- timestamp INTEGER NOT NULL,
- issent INTEGER NOT NULL
- );
- """;
-
- public SqliteMessageLog(Sqlite.Database db) throws SqliteDbError {
- this.db = db;
- init_db();
- sanitize_database();
- Logger.log(LogLevel.DEBUG, "SQLite database created.");
- }
-
- ~LocalStorage() {
- Logger.log(LogLevel.DEBUG, "SQLite database closed.");
- }
-
- public void connect_to(ToxSession session) {
- session.on_own_message.connect(on_outgoing_message);
- session.on_friend_message.connect(on_incoming_message);
- }
-
- public void disconnect_from(ToxSession session) {
- session.on_own_message.disconnect(on_outgoing_message);
- session.on_friend_message.disconnect(on_incoming_message);
- }
-
- private void on_incoming_message(Contact c, string message) {
- on_message(c, message, false);
- }
-
- private void on_outgoing_message(Contact c, string message) {
- on_message(c, message, true);
- }
-
- public void on_message(Contact c, string message, bool issender) {
- string cId = Tools.bin_to_hexstring(c.public_key);
- DateTime nowTime = new DateTime.now_utc();
-
- try {
- SqliteTools.put_text(insert_statement, TABLE_USER, myId);
- SqliteTools.put_text(insert_statement, TABLE_CONTACT, cId);
- SqliteTools.put_text(insert_statement, TABLE_MESSAGE, message);
- SqliteTools.put_int64(insert_statement, TABLE_TIME, nowTime.to_unix());
- SqliteTools.put_int(insert_statement, TABLE_SENDER, issender ? 1 : 0);
- } catch (SqliteStatementError e) {
- Logger.log(LogLevel.ERROR, "Error writing message to sqlite database: " + e.message);
- return;
- }
-
- insert_statement.step();
- insert_statement.reset();
- }
-
- public GLib.List? retrieve_history(Contact c) {
- string cId = Tools.bin_to_hexstring(c.public_key);
- try {
- SqliteTools.put_text(select_statement , TABLE_USER, myId);
- SqliteTools.put_text(select_statement , TABLE_CONTACT, cId);
- } catch (SqliteStatementError e) {
- Logger.log(LogLevel.ERROR, "Error retrieving logs from sqlite database: " + e.message);
- return null;
- }
-
- List messages = new List();
-
- while (select_statement.step () == Sqlite.ROW) {
- string message = select_statement.column_text(HistoryColumn.MESSAGE);
- int64 timestamp = select_statement.column_int64(HistoryColumn.TIME);
- bool issender = select_statement.column_int(HistoryColumn.SENDER) != 0;
-
- DateTime send_time = new DateTime.from_unix_utc (timestamp);
- if(issender) {
- messages.append(new Message.outgoing(c, message, send_time));
- } else {
- messages.append(new Message.incoming(c, message, send_time));
- }
- }
-
- select_statement.reset ();
- return messages;
- }
-
- public void sanitize_database() {
- if(Settings.instance.log_indefinitely) {
- return;
- }
- Logger.log(LogLevel.INFO, "Sanitizing database...");
- DateTime timestamp = new DateTime.now_utc().add_days(-Settings.instance.days_to_log);
- try {
- SqliteTools.put_int64(delete_statement, TABLE_TIME, timestamp.to_unix());
- } catch (SqliteStatementError e) {
- Logger.log(LogLevel.ERROR, "Error sanitizing sqlite database: " + e.message);
- return;
- }
-
- delete_statement.step();
- delete_statement.reset();
- }
-
- private void init_db() throws SqliteDbError {
- string errmsg;
-
- //create table and index if needed
- if (db.exec (QUERY_TABLE_HISTORY, null, out errmsg) != Sqlite.OK) {
- throw new SqliteDbError.QUERY(_("Error creating message log table: %s\n"), errmsg);
- }
-
- //prepare insert statement for adding new history messages
- if (db.prepare_v2 (STATEMENT_INSERT_HISTORY, STATEMENT_INSERT_HISTORY.length, out insert_statement) != Sqlite.OK) {
- throw new SqliteDbError.QUERY("Error creating message insert statement: %d: %s\n", db.errcode (), db.errmsg());
- }
-
- //prepare select statement to get history. Will execute on indexed data
- if (db.prepare_v2 (STATEMENT_SELECT_HISTORY, STATEMENT_SELECT_HISTORY.length, out select_statement) != Sqlite.OK) {
- throw new SqliteDbError.QUERY("Error creating message select statement: %d: %s\n", db.errcode (), db.errmsg());
- }
-
- //prepare delete statement
- if (db.prepare_v2 (STATEMENT_SANITIZE_DATABASE, STATEMENT_SANITIZE_DATABASE.length, out delete_statement) != Sqlite.OK) {
- throw new SqliteDbError.QUERY("Error creating message delete statement: %d: %s\n", db.errcode (), db.errmsg());
- }
- }
-
-
- }
-}
diff --git a/src/core/Notification.vala b/src/core/Notification.vala
deleted file mode 100644
index feccbe6..0000000
--- a/src/core/Notification.vala
+++ /dev/null
@@ -1,52 +0,0 @@
-/*
- * Notification.vala
- *
- * Copyright (C) 2013-2014 Venom authors and contributors
- *
- * This file is part of Venom.
- *
- * Venom is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * Venom is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with Venom. If not, see .
- */
-
- namespace Venom {
- public class Notification : GLib.Object {
- private Notification() {}
-
-#if ENABLE_LIBNOTIFY
- private static bool is_initialized = false;
- public static void show_notification_for_message(IMessage m) {
-
- if(!is_initialized) {
- Notify.init("Venom");
- is_initialized = true;
- }
- try {
- Notify.Notification notification = new Notify.Notification(
- m.get_notification_header(),
- m.get_message_plain(),
- null
- );
- notification.set_image_from_pixbuf(m.get_sender_image());
- notification.set_category("im.received");
- notification.set_hint("sound-name", new Variant.string("message-new-instant"));
- notification.show();
- } catch (Error e) {
- Logger.log(LogLevel.ERROR, _("Error showing notification: ") + e.message);
- }
- }
-#else
- public static void show_notification_for_message(IMessage m) {}
-#endif
- }
- }
diff --git a/src/core/NotificationListener.vala b/src/core/NotificationListener.vala
new file mode 100644
index 0000000..8d4a80e
--- /dev/null
+++ b/src/core/NotificationListener.vala
@@ -0,0 +1,92 @@
+/*
+ * NotificationListener.vala
+ *
+ * Copyright (C) 2018 Venom authors and contributors
+ *
+ * This file is part of Venom.
+ *
+ * Venom is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Venom is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Venom. If not, see .
+ */
+namespace Venom {
+ public interface NotificationListener : GLib.Object {
+ public abstract bool show_notifications { get; set; }
+ public abstract void on_unread_message(IMessage message, IContact sender);
+ public abstract void on_filetransfer(FileTransfer transfer, IContact sender);
+ public abstract void clear_notifications();
+ }
+
+ public class NotificationListenerImpl : NotificationListener, GLib.Object {
+ public bool show_notifications { get; set; }
+ private ILogger logger;
+ private static string message_id = "new-message";
+ private static string transfer_id = "new-transfer";
+
+ public NotificationListenerImpl(ILogger logger) {
+ this.logger = logger;
+ }
+
+ public virtual void on_unread_message(IMessage message, IContact sender) {
+ logger.d("on_unread_message");
+ if (!show_notifications || !sender.show_notifications()) {
+ return;
+ }
+
+ var app = GLib.Application.get_default() as Gtk.Application;
+ if (app == null) {
+ return;
+ }
+
+ var window = app.get_active_window();
+ if (window == null || window.is_active) {
+ return;
+ }
+
+ var notification = new Notification(_("New message from %s").printf(message.get_sender_plain()));
+ notification.set_body(message.get_message_plain());
+ notification.set_icon(message.get_sender_image());
+ notification.set_default_action_and_target_value("app.show-contact", new GLib.Variant.string(message.get_conversation_id()));
+ app.send_notification(message_id, notification);
+ }
+
+ public virtual void on_filetransfer(FileTransfer transfer, IContact sender) {
+ logger.d("on_filetransfer");
+ if (!show_notifications) {
+ return;
+ }
+
+ var app = GLib.Application.get_default() as Gtk.Application;
+ if (app == null) {
+ return;
+ }
+
+ var file_name = transfer.get_file_name();
+ var file_size = GLib.format_size(transfer.get_file_size());
+
+ var notification = new Notification(_("New file from %s").printf(sender.get_name_string()));
+ notification.set_body("%s (%s)".printf(file_name, file_size));
+ notification.set_icon(sender.get_image());
+ notification.set_default_action("app.show-filetransfers");
+ app.send_notification(transfer_id, notification);
+ }
+
+ public void clear_notifications() {
+ var app = GLib.Application.get_default() as Gtk.Application;
+ if (app == null) {
+ return;
+ }
+
+ app.withdraw_notification(message_id);
+ }
+ }
+}
diff --git a/src/core/ObservableList.vala b/src/core/ObservableList.vala
new file mode 100644
index 0000000..b50e9ad
--- /dev/null
+++ b/src/core/ObservableList.vala
@@ -0,0 +1,155 @@
+/*
+ * ObservableList.vala
+ *
+ * Copyright (C) 2018 Venom authors and contributors
+ *
+ * This file is part of Venom.
+ *
+ * Venom is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Venom is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Venom. If not, see .
+ */
+
+namespace Venom {
+ public class ObservableList : GLib.Object {
+ public signal void added(GLib.Object item, uint index);
+ public signal void removed(GLib.Object item, uint index);
+ public signal void changed();
+
+ private Gee.List list = new Gee.ArrayList();
+
+ public void set_list(GLib.List list) {
+ this.list.clear();
+ foreach (var item in list) {
+ this.list.add(item);
+ }
+ }
+
+ public void set_collection(Gee.Collection collection) {
+ this.list.clear();
+ foreach (var item in collection) {
+ this.list.add(item);
+ }
+ }
+
+ public void append(GLib.Object item) {
+ var idx = list.size;
+ list.add(item);
+ added(item, idx);
+ changed();
+ }
+
+ public void remove(GLib.Object item) {
+ var idx = list.index_of(item);
+ removed(item, idx);
+ list.remove_at(idx);
+ changed();
+ }
+
+ public uint length() {
+ return list.size;
+ }
+
+ public uint index(GLib.Object item) {
+ return (uint) list.index_of(item);
+ }
+
+ public GLib.Object nth_data(uint index) {
+ return list.@get((int) index);
+ }
+ }
+
+ public class ObservableListModel : GLib.Object, GLib.ListModel {
+ protected ObservableList list;
+ public ObservableListModel(ObservableList list) {
+ this.list = list;
+ list.added.connect(on_added);
+ list.removed.connect(on_removed);
+ }
+
+ protected virtual void on_added(GLib.Object item, uint index) {
+ items_changed(index, 0, 1);
+ }
+
+ protected virtual void on_removed(GLib.Object item, uint index) {
+ items_changed(index, 1, 0);
+ }
+
+ public virtual GLib.Object ? get_item(uint index) {
+ return list.nth_data(index) as GLib.Object;
+ }
+
+ public virtual GLib.Type get_item_type() {
+ return typeof (GLib.Object);
+ }
+
+ public virtual uint get_n_items() {
+ return list.length();
+ }
+
+ public virtual GLib.Object ? get_object(uint index) {
+ return get_item(index);
+ }
+ }
+
+ public class LazyObservableListModel : ObservableListModel {
+ private const int NUM_ENTRIES_PER_ITERATION = 10;
+ protected ILogger logger;
+ private uint index = 0;
+ private bool initialized = false;
+ public LazyObservableListModel(ILogger logger, ObservableList list, Cancellable? cancellable = null) {
+ base(list);
+ this.logger = logger;
+ initialize.begin(cancellable);
+ }
+
+ private async void initialize(Cancellable? cancellable = null) {
+ logger.d("LazyObservableListModel init started.");
+ while (list.length() > 0 && index < list.length()) {
+ if (cancellable != null && cancellable.is_cancelled()) {
+ logger.d("LazyObservableListModel init cancelled.");
+ return;
+ }
+
+ var num_entries = uint.min(list.length(), index + NUM_ENTRIES_PER_ITERATION) - index;
+ items_changed(index, 0, num_entries);
+ index += num_entries;
+ logger.d(@"LazyObservableListModel init $num_entries more entries.");
+ Idle.add(initialize.callback);
+ yield;
+ }
+ initialized = true;
+ logger.d("LazyObservableListModel init finished.");
+ }
+
+ protected override void on_added(GLib.Object item, uint index) {
+ if (!initialized) {
+ // ignore while not initialized
+ return;
+ }
+ items_changed(index, 0, 1);
+ }
+
+ protected override void on_removed(GLib.Object item, uint index) {
+ if (!initialized) {
+ // ignore while not initialized
+ return;
+ }
+ items_changed(index, 1, 0);
+ }
+
+ public override uint get_n_items() {
+ return initialized ? list.length() : uint.min(index, list.length());
+ }
+ }
+
+}
diff --git a/src/core/R.vala b/src/core/R.vala
new file mode 100644
index 0000000..4935e9b
--- /dev/null
+++ b/src/core/R.vala
@@ -0,0 +1,98 @@
+/*
+ * R.vala
+ *
+ * Copyright (C) 2013-2018 Venom authors and contributors
+ *
+ * This file is part of Venom.
+ *
+ * Venom is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Venom is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Venom. If not, see .
+ */
+
+namespace Venom {
+ public sealed class R {
+ private R() {}
+
+ private static IconResource _icons;
+ private static StringResource _strings;
+ private static ConstantsResource _constants;
+
+ public static IconResource icons {
+ get {
+ if (_icons == null) {
+ _icons = new IconResource();
+ }
+ return _icons;
+ }
+ }
+
+ public static StringResource strings {
+ get {
+ if (_strings == null) {
+ _strings = new StringResource();
+ }
+ return _strings;
+ }
+ }
+
+ public static ConstantsResource constants {
+ get {
+ if (_constants == null) {
+ _constants = new ConstantsResource();
+ }
+ return _constants;
+ }
+ }
+
+ public sealed class IconResource {
+ public string app { get { return "venom-symbolic"; } }
+
+ public string idle { get { return "idle-symbolic"; } }
+ public string busy { get { return "busy-symbolic"; } }
+ public string offline { get { return "offline-symbolic"; } }
+ public string online { get { return "online-symbolic"; } }
+
+ public string default_contact { get { return "friend-symbolic"; } }
+ public string default_groupchat { get { return "conference-symbolic"; } }
+ }
+
+ public sealed class StringResource {
+ public string default_username() { return _("Tox User"); }
+ public string default_statusmessage() { return ""; }
+ }
+
+ public sealed class ConstantsResource {
+ public string user_config_dir { get; set; default = GLib.Environment.get_user_config_dir(); }
+ public string downloads_dir { get; set; default = GLib.Environment.get_user_special_dir(GLib.UserDirectory.DOWNLOAD); }
+ public string profile_name { get; set; default = "tox"; }
+ public string avatars_folder() { return GLib.Path.build_filename(user_config_dir, "tox", "avatars"); }
+ public string window_state_filename() { return GLib.Path.build_filename(user_config_dir, "tox", profile_name + ".json"); }
+ public string db_filename() { return GLib.Path.build_filename(user_config_dir, "tox", profile_name + ".db"); }
+ public string tox_data_filename() { return GLib.Path.build_filename(user_config_dir, "tox", profile_name + ".data"); }
+ public string icons_prefix() { return "/chat/tox/venom/icons/scalable/status/"; }
+ public string icons_suffix() { return ".svg"; }
+ public string app_id() { return "chat.tox.venom"; }
+ public string tox_about() { return "https://tox.chat/about.html"; }
+ public string tox_get_involved() { return "https://wiki.tox.chat/users/contributing"; }
+ }
+ }
+
+ public static Gdk.Pixbuf ? pixbuf_from_resource(string res, int size = 96) {
+ try {
+ var resource_path = GLib.Path.build_path("/", R.constants.icons_prefix(), res + R.constants.icons_suffix());
+ return new Gdk.Pixbuf.from_resource_at_scale(resource_path, size, size, true);
+ } catch (Error e) {
+ }
+ return null;
+ }
+}
diff --git a/src/core/ResourceFactory.vala b/src/core/ResourceFactory.vala
deleted file mode 100644
index dd4787e..0000000
--- a/src/core/ResourceFactory.vala
+++ /dev/null
@@ -1,128 +0,0 @@
-/*
- * ResourceFactory.vala
- *
- * Copyright (C) 2013-2014 Venom authors and contributors
- *
- * This file is part of Venom.
- *
- * Venom is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * Venom is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with Venom. If not, see .
- */
-
-namespace Venom {
- public class ResourceFactory : GLib.Object{
-
- private static ResourceFactory? _instance;
- public static ResourceFactory instance {
- get {
- if( _instance == null )
- _instance = new ResourceFactory();
- return _instance;
- }
- private set {
- _instance = value;
- }
- }
-
- private ResourceFactory () {
- string theme_folder = Path.build_filename(Tools.find_data_dir(), "theme");
-
- arrow = load_image_from_resource("/org/gtk/venom/pixmaps/button_icons/arrow_white.png");
- send_file = load_image_from_resource("/org/gtk/venom/pixmaps/button_icons/attach.png");
- call = load_image_from_resource("/org/gtk/venom/pixmaps/button_icons/call.png");
- ok = load_image_from_resource("/org/gtk/venom/pixmaps/button_icons/check.png");
- smiley = load_image_from_resource("/org/gtk/venom/pixmaps/button_icons/emoticon.png");
- cancel = load_image_from_resource("/org/gtk/venom/pixmaps/button_icons/no.png");
- send = load_image_from_resource("/org/gtk/venom/pixmaps/button_icons/sendmessage.png");
- call_video = load_image_from_resource("/org/gtk/venom/pixmaps/button_icons/video.png");
-
- add = load_image_from_resource("/org/gtk/venom/pixmaps/contact_list_icons/add.png");
- groupchat = load_image_from_resource("/org/gtk/venom/pixmaps/contact_list_icons/group.png");
- settings = load_image_from_resource("/org/gtk/venom/pixmaps/contact_list_icons/settings.png");
- filetransfer = load_image_from_resource("/org/gtk/venom/pixmaps/contact_list_icons/transfer.png");
-
- away = load_image_from_resource("/org/gtk/venom/pixmaps/status/dot_idle.png");
- away_glow = load_image_from_resource("/org/gtk/venom/pixmaps/status/dot_idle_notification.png");
- busy = load_image_from_resource("/org/gtk/venom/pixmaps/status/dot_busy.png");
- busy_glow = load_image_from_resource("/org/gtk/venom/pixmaps/status/dot_busy_notification.png");
- offline = load_image_from_resource("/org/gtk/venom/pixmaps/status/dot_away.png");
- offline_glow = load_image_from_resource("/org/gtk/venom/pixmaps/status/dot_away_notification.png");
- online = load_image_from_resource("/org/gtk/venom/pixmaps/status/dot_online.png");
- online_glow = load_image_from_resource("/org/gtk/venom/pixmaps/status/dot_online_notification.png");
-
- default_contact = load_image_from_resource("/org/gtk/venom/pixmaps/user_icons/default_contact.png");
- default_groupchat = load_image_from_resource("/org/gtk/venom/pixmaps/user_icons/default_groupchat.png");
-
- default_theme_filename = Path.build_filename(theme_folder, "default.css");
-
-
- tox_config_dir = Path.build_filename(GLib.Environment.get_user_config_dir(), "tox");
- data_filename = Path.build_filename(tox_config_dir, "data");
- db_filename = Path.build_filename(tox_config_dir, "tox.db");
- config_filename = Path.build_filename(tox_config_dir, "config.json");
-
- default_username = _("Tox User");
- default_statusmessage = _("Toxing on Venom v.%s").printf(Config.VERSION);
- }
-
- public Gdk.Pixbuf ok {get; private set;}
- public Gdk.Pixbuf cancel {get; private set;}
-
- public Gdk.Pixbuf away {get; private set;}
- public Gdk.Pixbuf away_glow {get; private set;}
- public Gdk.Pixbuf busy {get; private set;}
- public Gdk.Pixbuf busy_glow {get; private set;}
- public Gdk.Pixbuf offline {get; private set;}
- public Gdk.Pixbuf offline_glow {get; private set;}
- public Gdk.Pixbuf online {get; private set;}
- public Gdk.Pixbuf online_glow {get; private set;}
-
- public Gdk.Pixbuf call {get; private set;}
- public Gdk.Pixbuf call_video {get; private set;}
- public Gdk.Pixbuf send {get; private set;}
-
- public Gdk.Pixbuf send_file {get; private set;}
- public Gdk.Pixbuf smiley {get; private set;}
-
- public Gdk.Pixbuf add {get; private set;}
- public Gdk.Pixbuf groupchat {get; private set;}
- public Gdk.Pixbuf settings {get; private set;}
- public Gdk.Pixbuf filetransfer {get; private set;}
-
- public Gdk.Pixbuf default_contact {get; private set;}
- public Gdk.Pixbuf default_groupchat {get; private set;}
-
- public Gdk.Pixbuf arrow {get; private set;}
-
- public string default_theme_filename {get; private set;}
- public string tox_config_dir {get; private set;}
- public string data_filename {get; set;}
- public string db_filename {get; set;}
- public string config_filename {get; set;}
- public string default_username {get; private set;}
- public string default_statusmessage {get; private set;}
-
- public bool offline_mode {get; set; default = false;}
- public bool textview_mode {get; set; default = false;}
-
- private Gdk.Pixbuf? load_image_from_resource(string resourcename) {
- Gdk.Pixbuf buf = null;
- try {
- buf = new Gdk.Pixbuf.from_resource( resourcename );
- } catch (Error e) {
- Logger.log(LogLevel.ERROR, "Error while loading image from \"" + resourcename + "\": " + e.message);
- }
- return buf;
- }
- }
-}
diff --git a/src/core/Settings.vala b/src/core/Settings.vala
deleted file mode 100644
index a9905eb..0000000
--- a/src/core/Settings.vala
+++ /dev/null
@@ -1,123 +0,0 @@
-/*
- * Settings.vala
- *
- * Copyright (C) 2013-2014 Venom authors and contributors
- *
- * This file is part of Venom.
- *
- * Venom is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * Venom is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with Venom. If not, see .
- */
-
-namespace Venom {
- public class Settings : Object {
-
- public const string MESSAGE_LOGGING_KEY = "enable-logging";
- public const string DAYS_TO_LOG_KEY = "days-to-log";
- public const string LOG_INDEFINITELY_KEY = "log-indefinitely";
- public const string URGENCY_NOTIFICATION_KEY = "enable-urgency-notification";
- public const string TRAY_KEY = "enable-tray";
- public const string NOTIFY_KEY = "enable-notify";
- public const string DEC_BINARY_PREFIX_KEY = "dec-binary-prefix";
- public const string SEND_TYPING_STATUS_KEY = "send-typing-status";
- public const string SHOW_TYPING_STATUS_KEY = "show-typing-status";
- public const string DEFAULT_HOST_KEY = "default-host";
-
- public bool enable_logging { get; set; default = false; }
- public bool enable_urgency_notification { get; set; default = true; }
- public bool log_indefinitely { get; set; default = true; }
- public int days_to_log { get; set; default = 180; }
- public bool dec_binary_prefix { get; set; default = true; }
- public bool send_typing_status { get; set; default = false; }
- public bool show_typing_status { get; set; default = true; }
- public int contactlist_width { get; set; default = 200; }
- public int contactlist_height { get; set; default = 600; }
- public int window_width { get; set; default = 600; }
- public int window_height { get; set; default = 600; }
- public string default_host { get; set; default = "toxme.se";}
- public bool enable_tray { get; set; default = false; }
- public bool enable_notify { get; set; default = false; }
-
- private static Settings? _instance;
- public static Settings instance {
- get {
- if( _instance == null ) {
- File tmp = File.new_for_path(ResourceFactory.instance.config_filename);
- if (tmp.query_exists()) {
- _instance = load_settings(ResourceFactory.instance.config_filename) ?? new Settings();
- } else {
- _instance = new Settings();
- }
- }
- return _instance;
- }
- private set {
- _instance = value;
- }
- }
-
- private Settings() {
- }
-
- private string filepath;
- private bool timeout_started;
- private bool timeout_function() {
- // save only if not saved previously
- if( timeout_started ) {
- save_settings(filepath);
- }
- return false;
- }
-
- public void save_settings_with_timeout(string path_to_file) {
- // only add timeout function once
- if( !timeout_started ) {
- timeout_started = true;
- filepath = path_to_file;
- Timeout.add_seconds(1, timeout_function);
- }
- }
-
- public void save_settings(string path_to_file) {
- timeout_started = false;
- Json.Node root = Json.gobject_serialize (this);
-
- Json.Generator generator = new Json.Generator ();
- generator.set_root (root);
- generator.pretty = true;
-
- File file = File.new_for_path(path_to_file);
- try {
- DataOutputStream os = new DataOutputStream(file.replace(null, false, FileCreateFlags.PRIVATE | FileCreateFlags.REPLACE_DESTINATION ));
- generator.to_stream(os);
- } catch (Error e) {
- Logger.log(LogLevel.ERROR, "Error saving configs: " + e.message);
- return;
- }
- Logger.log(LogLevel.INFO, "Settings saved.");
- }
-
- public static Settings? load_settings(string path) {
- Json.Node node;
- try {
- Json.Parser parser = new Json.Parser();
- parser.load_from_file(path);
- node = parser.get_root();
- } catch (Error e) {
- Logger.log(LogLevel.ERROR, "Error reading configs: " + e.message);
- return null;
- }
- return Json.gobject_deserialize (typeof (Settings), node) as Settings;
- }
- }
-}
diff --git a/src/core/SqliteTools.vala b/src/core/SqliteTools.vala
deleted file mode 100644
index a4913d3..0000000
--- a/src/core/SqliteTools.vala
+++ /dev/null
@@ -1,79 +0,0 @@
-/*
- * SqliteTools.vala
- *
- * Copyright (C) 2013-2014 Venom authors and contributors
- *
- * This file is part of Venom.
- *
- * Venom is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * Venom is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with Venom. If not, see .
- */
-
-namespace Venom {
- public errordomain SqliteStatementError {
- INDEX,
- BIND
- }
- public errordomain SqliteDbError {
- OPEN,
- QUERY
- }
- public class SqliteTools {
- private SqliteTools() {}
-
- public static void put_int(Sqlite.Statement statement, string name, int value) throws SqliteStatementError {
- int index = statement.bind_parameter_index(name);
- if(index == 0) {
- throw new SqliteStatementError.INDEX(_("Index for %s not found.").printf(name));
- }
- if(statement.bind_int(index, value) != Sqlite.OK) {
- throw new SqliteStatementError.BIND(_("Could not bind int to %s.").printf(name));
- }
- }
-
- public static void put_int64(Sqlite.Statement statement, string name, int64 value) throws SqliteStatementError {
- int index = statement.bind_parameter_index(name);
- if(index == 0) {
- throw new SqliteStatementError.INDEX(_("Index for %s not found.").printf(name));
- }
- if(statement.bind_int64(index, value) != Sqlite.OK) {
- throw new SqliteStatementError.BIND(_("Could not bind int64 to %s.").printf(name));
- }
- }
-
- public static void put_text(Sqlite.Statement statement, string name, string value) throws SqliteStatementError {
- int index = statement.bind_parameter_index(name);
- if(index == 0) {
- throw new SqliteStatementError.INDEX(_("Index for %s not found.").printf(name));
- }
- if(statement.bind_text(index, value) != Sqlite.OK) {
- throw new SqliteStatementError.BIND(_("Could not bind text to %s").printf(name));
- }
- }
-
- public static void open_db(string filepath, out Sqlite.Database db) throws SqliteDbError, Error {
-
- // Open/Create a database:
- File file = File.new_for_path(filepath);
- if(file.query_exists()) {
- GLib.FileUtils.chmod(filepath, 0600);
- } else {
- file.create(GLib.FileCreateFlags.PRIVATE);
- }
-
- if(Sqlite.Database.open (filepath, out db) != Sqlite.OK) {
- throw new SqliteDbError.OPEN(_("Can't open database: %d: %s\n"), db.errcode (), db.errmsg ());
- }
- }
- }
-}
diff --git a/src/core/TimeStamp.vala b/src/core/TimeStamp.vala
new file mode 100644
index 0000000..42003be
--- /dev/null
+++ b/src/core/TimeStamp.vala
@@ -0,0 +1,48 @@
+/*
+ * TimeStamp.vala
+ *
+ * Copyright (C) 2018 Venom authors and contributors
+ *
+ * This file is part of Venom.
+ *
+ * Venom is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Venom is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Venom. If not, see .
+ */
+
+namespace Venom.TimeStamp {
+ public static string get_pretty_timestamp(GLib.DateTime timestamp, GLib.DateTime now = new GLib.DateTime.now_local()) {
+ var just_now = now.add_minutes(-1);
+ if (timestamp.compare(just_now) > 0) {
+ return _("Just now");
+ }
+ var minutes_ago = now.add_minutes(-59);
+ if (timestamp.compare(minutes_ago) > 0) {
+ var minutes = (uint) (now.difference(timestamp) / GLib.TimeSpan.MINUTE);
+ return ngettext("%u minute ago", "%u minutes ago", minutes).printf(minutes);
+ }
+ var hours_ago = now.add_hours(-6);
+ if (timestamp.compare(hours_ago) > 0) {
+ var hours = (uint) (now.difference(timestamp) / GLib.TimeSpan.HOUR);
+ return ngettext("%u hour ago", "%u hours ago", hours).printf(hours);
+ }
+ var midnight = new GLib.DateTime.local(now.get_year(), now.get_month(), now.get_day_of_month(), 0, 0, 0);
+ if (timestamp.compare(midnight) > 0) {
+ return _("Today at %s").printf(timestamp.format("%X"));
+ }
+ var yesterday = midnight.add_days(-1);
+ if (timestamp.compare(yesterday) > 0) {
+ return _("Yesterday at %s").printf(timestamp.format("%X"));
+ }
+ return timestamp.format("%c");
+ }
+}
diff --git a/src/core/Tools.vala b/src/core/Tools.vala
index b3e37b7..7295a83 100644
--- a/src/core/Tools.vala
+++ b/src/core/Tools.vala
@@ -20,58 +20,35 @@
*/
namespace Venom {
- public class Tools : GLib.Object{
- // find our data dir (on linux most likely /usr/share or /usr/local/share)
- public static string find_data_dir() {
- //System data directory
- foreach (string s in GLib.Environment.get_system_data_dirs()) {
- string dir = Path.build_filename(s, "venom");
- File f = File.new_for_path(dir);
- if(f.query_exists())
- return dir;
- }
- // Check for common directories on portable versions
- string[] portable_directories = {
- Path.build_filename(GLib.Environment.get_user_data_dir(), "venom"),
- Path.build_filename("share", "venom"),
- Path.build_filename("..", "share", "venom")
- };
- for (int i = 0; i < portable_directories.length; ++i) {
- File f = File.new_for_path(portable_directories[i]);
- if(f.query_exists())
- return portable_directories[i];
- }
-
- // Assume that our current pwd is our data dir
- return "";
- }
+ public class Tools {
+ private Tools() {}
public static void create_path_for_file(string filename, int mode) {
string pathname = Path.get_dirname(filename);
File path = File.new_for_path(pathname);
- if(!path.query_exists()) {
+ if (!path.query_exists()) {
DirUtils.create_with_parents(pathname, mode);
- Logger.log(LogLevel.INFO, "created directory " + pathname);
+ // Logger.log(LogLevel.INFO, "created directory " + pathname);
}
}
// convert a hexstring to uint8[]
public static uint8[] hexstring_to_bin(string s) {
- uint8[] buf = new uint8[s.length / 2];
- for(int i = 0; i < buf.length; ++i) {
- int b = 0;
- s.substring(2*i, 2).scanf("%02x", ref b);
- buf[i] = (uint8)b;
+ var buf = new uint8[s.length / 2];
+ var b = 0;
+ for (int i = 0; i < buf.length; ++i) {
+ s.substring(2 * i, 2).scanf("%02x", ref b);
+ buf[i] = (uint8) b;
}
return buf;
}
// convert a uint8[] to string
public static string bin_to_hexstring(uint8[] bin)
- requires(bin.length != 0)
+ requires(bin.length != 0)
{
- StringBuilder b = new StringBuilder();
- for(int i = 0; i < bin.length; ++i) {
+ var b = new StringBuilder();
+ for (int i = 0; i < bin.length; ++i) {
b.append("%02X".printf(bin[i]));
}
return b.str;
@@ -81,9 +58,9 @@ namespace Venom {
//TODO optimize this
uint8[] buf = new uint8[data.length + 1];
Memory.copy(buf, data, data.length);
- string sbuf = (string)buf;
+ string sbuf = (string) buf;
- if(sbuf.validate()) {
+ if (sbuf.validate()) {
return sbuf;
}
// Extract usable parts of the string
@@ -93,7 +70,7 @@ namespace Venom {
if (u != (unichar) (-1)) {
sb.append_unichar(u);
} else {
- Logger.log(LogLevel.WARNING, "Invalid UTF-8 character detected");
+ // Logger.log(LogLevel.WARNING, "Invalid UTF-8 character detected");
}
}
return sb.str;
@@ -101,61 +78,37 @@ namespace Venom {
public static string shorten_name(string name) {
string[] parts = Regex.split_simple("\\s",name);
- if(parts.length < 2) return name;
+ if (parts.length < 2) { return name; }
return parts[0];
}
public static string remove_whitespace(string str) {
try {
- var regex = new GLib.Regex ("\\s");
+ var regex = new GLib.Regex("\\s");
return(regex.replace(str, -1, 0, ""));
} catch (GLib.RegexError e) {
- GLib.assert_not_reached ();
+ GLib.assert_not_reached();
}
}
- public static string markup_uris(string text) {
- string escaped_text = Markup.escape_text(text);
- string ret;
- try {
- ret = Tools.uri_regex.replace(escaped_text, -1, 0, "\">\\g");
- } catch (GLib.RegexError e) {
- Logger.log(LogLevel.ERROR, "Error when doing uri markup: " + e.message);
- return text;
- }
- return ret;
+ public static uint64 get_file_size(GLib.File file) throws Error {
+ var is = file.read();
+ is.seek(0, SeekType.END);
+ return is.tell();
}
- public static string friend_add_error_to_string(Tox.FriendAddError friend_add_error) {
- switch(friend_add_error) {
- case Tox.FriendAddError.TOOLONG:
- return _("Message too long");
- case Tox.FriendAddError.NOMESSAGE:
- return _("No message included");
- case Tox.FriendAddError.OWNKEY:
- return _("Can't send to own key");
- case Tox.FriendAddError.ALREADYSENT:
- return _("Friend request already sent");
- case Tox.FriendAddError.UNKNOWN:
- return _("Unknown error");
- case Tox.FriendAddError.BADCHECKSUM:
- return _("Bad checksum");
- case Tox.FriendAddError.SETNEWNOSPAM:
- return _("Set new nospam");
- case Tox.FriendAddError.NOMEM:
- return _("Out of memory");
- default:
- return _("Friend request successfully sent");
- }
+ public static string markup_uris(string text) throws Error {
+ return Tools.uri_regex.replace(text, -1, 0, "\">\\g");
}
+
private static GLib.Regex _action_regex;
public static GLib.Regex action_regex {
get {
- if(_action_regex == null) {
+ if (_action_regex == null) {
try {
_action_regex = new GLib.Regex("^/(?P\\S+)(\\s+(?P.+))?$");
} catch (GLib.RegexError e) {
- Logger.log(LogLevel.ERROR, "Can't create action regex: " + e.message);
+ // Logger.log(LogLevel.ERROR, "Can't create action regex: " + e.message);
}
}
return _action_regex;
@@ -164,11 +117,11 @@ namespace Venom {
private static GLib.Regex _uri_regex;
public static GLib.Regex uri_regex {
get {
- if(_uri_regex == null) {
+ if (_uri_regex == null) {
try {
- _uri_regex = new GLib.Regex("(?[a-z]+://\\S*)");
+ _uri_regex = new GLib.Regex("(?[a-z]+://\\S*)");
} catch (GLib.RegexError e) {
- Logger.log(LogLevel.ERROR, "Can't create uri regex: " + e.message);
+ // Logger.log(LogLevel.ERROR, "Can't create uri regex: " + e.message);
}
}
return _uri_regex;
diff --git a/src/core/ToxDns.vala b/src/core/ToxDns.vala
deleted file mode 100644
index c5fb911..0000000
--- a/src/core/ToxDns.vala
+++ /dev/null
@@ -1,141 +0,0 @@
-/*
- * ToxDns.vala
- *
- * Copyright (C) 2013-2014 Venom authors and contributors
- *
- * This file is part of Venom.
- *
- * Venom is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * Venom is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with Venom. If not, see .
- */
-
-//TODO make asynchronous
-namespace Venom {
- public class ToxDns : GLib.Object{
- public delegate string? pin_request_delegate(string? tox_dns_id = null);
- public string default_host { get; set; default = "";}
- public string? authority_user {get; private set; default = null;}
-
- private static GLib.Regex _tox_dns_record_regex;
- public static GLib.Regex tox_dns_record_regex {
- get {
- if(_tox_dns_record_regex == null) {
- try {
- _tox_dns_record_regex = new GLib.Regex("^v=(?P[^\\W;]+);(id=(?P[^\\W;]+)|pub=(?P[^\\W;]+);check=(?P[^\\W;]+))");
- } catch (GLib.Error e) {
- Logger.log(LogLevel.FATAL, "Error creating tox dns regex: " + e.message);
- }
- }
- return _tox_dns_record_regex;
- }
- }
-
- private static GLib.Regex _tox_uri_regex;
- public static GLib.Regex tox_uri_regex {
- get {
- if(_tox_uri_regex == null) {
- try {
- //TODO support message pin and xname (ignored for now)
- _tox_uri_regex = new GLib.Regex("^((?Ptox)://)?((?P[[:xdigit:]]{%i})|(?P[[:digit:][:alpha:]]+)(@(?P[[:digit:][:alpha:]]+(\\.[[:digit:][:alpha:]]+)+))?)".printf(Tox.FRIEND_ADDRESS_SIZE * 2));
- } catch (GLib.Error e) {
- Logger.log(LogLevel.FATAL, "Error creating tox uri regex: " + e.message);
- }
- }
- return _tox_uri_regex;
- }
- }
-
- public string? resolve_id(string tox_uri, pin_request_delegate pin_request) {
- string hostname = null, tox_dns_id = null;
- authority_user = null;
-
- GLib.MatchInfo info = null;
- if(tox_uri_regex == null || !tox_uri_regex.match(tox_uri, 0, out info)) {
- Logger.log(LogLevel.ERROR, "Invalid tox uri");
- return null;
- }
-
- authority_user = info.fetch_named("authority_user");
- if(authority_user == null) {
- // must be tox:// in this case
- return info.fetch_named("tox_id");
- }
-
- string authority_host = info.fetch_named("authority_host") ?? default_host;
- hostname = authority_user + "._tox." + authority_host;
- tox_dns_id = authority_user + "@" + authority_host;
- string record = null;
- try {
- record = lookup_dns_record(hostname);
- } catch (GLib.Error e) {
- Logger.log(LogLevel.ERROR, "Error resolving name: " + e.message);
- return null;
- }
-
- return get_id_from_dns_record(tox_dns_id, record, pin_request);
- }
-
- private string? get_id_from_dns_record(string tox_dns_id, string dns_record, pin_request_delegate pin_request) {
- GLib.MatchInfo info = null;
- if(tox_dns_record_regex != null && tox_dns_record_regex.match(dns_record, 0, out info)) {
- string v = info.fetch_named("v");
- switch(v) {
- case "tox1":
- string id = info.fetch_named("id");
- Logger.log(LogLevel.INFO, "tox 1 ID found: " + id);
- return id;
- case "tox2":
- string pub = info.fetch_named("pub");
- string check = info.fetch_named("check");
- Logger.log(LogLevel.INFO, "tox 2 ID found: " + pub + " " + check);
- string pin = pin_request(tox_dns_id);
- if(pin == null || pin == "") {
- Logger.log(LogLevel.INFO, "No pin privided, aborting...");
- return null;
- }
- string decoded = pub + Venom.Tools.bin_to_hexstring(Base64.decode(pin + "==")) + check;
- Logger.log(LogLevel.INFO, "decoded: " + decoded);
- return decoded;
- default:
- assert_not_reached();
- }
- } else {
- Logger.log(LogLevel.INFO, "Invalid record");
- }
- return null;
- }
-
- private string? lookup_dns_record(string hostname) throws GLib.Error {
-#if ENABLE_DJBDNS
- DJBDns.AllocatedString answer = DJBDns.AllocatedString();
- DJBDns.AllocatedString fqdn = {hostname, hostname.length, 0};
- int ret = DJBDns.dns_txt(out answer, fqdn);
- if(ret == 0) {
- return answer.s[0:answer.len];
- }
-#else
- GLib.Resolver resolver = GLib.Resolver.get_default();
- GLib.List records = resolver.lookup_records(hostname, GLib.ResolverRecordType.TXT);
- if( records.length() > 0 ) {
- VariantIter it;
- string s;
- records.data.get("(as)", out it);
- if(it.next("s", out s)) {
- return s;
- }
- }
-#endif
- return null;
- }
- }
-}
diff --git a/src/core/ToxSession.vala b/src/core/ToxSession.vala
deleted file mode 100644
index 16f7939..0000000
--- a/src/core/ToxSession.vala
+++ /dev/null
@@ -1,878 +0,0 @@
-/*
- * ToxSession.vala
- *
- * Copyright (C) 2013-2014 Venom authors and contributors
- *
- * This file is part of Venom.
- *
- * Venom is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * Venom is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with Venom. If not, see .
- */
-
-namespace Venom {
- public enum UserStatus {
- ONLINE,
- AWAY,
- BUSY,
- OFFLINE;
- public string to_string() {
- switch (this) {
- case ONLINE:
- return _("Online");
- case AWAY:
- return _("Away");
- case BUSY:
- return _("Busy");
- case OFFLINE:
- return _("Offline");
- default:
- assert_not_reached();
- }
- }
- }
-
- // Wrapper class for accessing tox functions threadsafe
- public class ToxSession : Object {
- private Tox.Tox handle;
- private IMessageLog message_log;
- private IContactStorage contact_storage;
- private IDhtNodeStorage dht_node_storage;
- private Sqlite.Database db;
-
- private DhtNode[] dht_nodes = {};
- private GLib.HashTable _contacts = new GLib.HashTable(null, null);
- private GLib.HashTable _groups = new GLib.HashTable(null, null);
- private Thread session_thread = null;
- private bool bootstrapped = false;
- private bool ipv6 = false;
- public bool running {get; private set; default=false; }
- public bool connected { get; private set; default=false; }
- public DhtNode connected_dht_node { get; private set; default=null; }
-
- // Core functionality signals
- public signal void on_friend_request(Contact c, string message);
- public signal void on_friend_message(Contact c, string message);
- public signal void on_own_message(Contact c, string message);
- public signal void on_own_action(Contact c, string action);
- public signal void on_friend_action(Contact c, string action);
- public signal void on_name_change(Contact c, string? old_name);
- public signal void on_status_message(Contact c, string? old_status);
- public signal void on_user_status(Contact c, uint8 old_status);
- public signal void on_read_receipt(Contact c, uint32 receipt);
- public signal void on_connection_status(Contact c);
- public signal void on_own_connection_status(bool status);
- public signal void on_own_user_status(UserStatus status);
- public signal void on_typing_change(Contact c, bool is_typing);
-
- // Groupchat signals
- public signal void on_group_invite(Contact c, GroupChat g);
- public signal void on_group_message(GroupChat g, int peernumber, string message);
- public signal void on_group_action(GroupChat g, int peernumber, string action);
- public signal void on_group_peer_changed(GroupChat g, int peernumber, Tox.ChatChange change);
-
- // File sending callbacks
-
- public signal void on_file_sendrequest(int friendnumber,uint8 filenumber,uint64 filesize,string filename);
- public signal void on_file_control(int friendnumber, uint8 filenumber,uint8 receive_send,uint8 status,uint8[] data);
- public signal void on_file_data(int friendnumber,uint8 filenumber,uint8[] data);
-
-
- public ToxSession( bool ipv6 = false ) {
- this.ipv6 = ipv6;
-
- Tox.Options options = Tox.Options();
-
- string[] proxy_strings = {};
- ProxyResolver proxy_resolver = ProxyResolver.get_default();
- try {
- proxy_strings = proxy_resolver.lookup("socks://tox.im");
- } catch (Error e) {
- Logger.log(LogLevel.ERROR, "Error when looking up proxy settings");
- }
-
- Regex proxy_regex = null;
- try {
- proxy_regex = new GLib.Regex("^(?Psocks5)://((?P[^:]*)(:(?P.*))?@)?(?P.*):(?P.*)");
- } catch (GLib.Error e) {
- Logger.log(LogLevel.FATAL, "Error creating tox uri regex: " + e.message);
- }
-
- foreach(unowned string proxy in proxy_strings) {
- if(proxy.has_prefix("socks5:")) {
- Logger.log(LogLevel.INFO, "socks5 proxy found: " + proxy);
- GLib.MatchInfo info = null;
- if(proxy_regex != null && proxy_regex.match(proxy, 0, out info)) {
- string proxy_host = info.fetch_named("host");
- string proxy_port = info.fetch_named("port");
- options.proxy_enabled = 1;
- options.udp_disabled = 1;
- Memory.copy(*(&options.proxy_address), proxy_host.data, int.min(proxy_host.length, options.proxy_address.length));
- options.proxy_port = (uint16)int.parse(proxy_port);
- break;
- } else {
- Logger.log(LogLevel.INFO, "socks5 proxy does not match regex");
- }
- }
- }
-
- options.ipv6enabled = ipv6 ? 1 : 0;
-
- // create handle
- handle = new Tox.Tox(options);
-
- //start local storage
- try {
- SqliteTools.open_db(ResourceFactory.instance.db_filename, out db);
-
- if(Settings.instance.enable_logging) {
- message_log = new SqliteMessageLog(db);
- message_log.connect_to(this);
- } else {
- message_log = new DummyMessageLog();
- }
- contact_storage = new SqliteContactStorage(db);
- dht_node_storage = new DummyDhtNodeStorage();
- //unfinished, so replaced with dummy storage
- //dht_node_storage = new SqliteDhtNodeStorage(db);
- } catch (Error e) {
- Logger.log(LogLevel.ERROR, "Error opening database: " + e.message);
- message_log = new DummyMessageLog();
- dht_node_storage = new DummyDhtNodeStorage();
- }
-
- init_dht_nodes();
- init_callbacks();
- }
-
- // destructor
- ~ToxSession() {
- running = false;
- }
-
- private void init_dht_nodes() {
- dht_nodes = dht_node_storage.get_dht_nodes();
- if(dht_nodes.length == 0) {
- DummyDhtNodeStorage dummy_storage = new DummyDhtNodeStorage();
- dht_nodes = dummy_storage.get_dht_nodes();
- }
- }
-
- private void init_callbacks() {
- // setup callbacks
- handle.callback_friend_request(this.on_friend_request_callback);
- handle.callback_friend_message(this.on_friend_message_callback);
- handle.callback_friend_action(this.on_friend_action_callback);
- handle.callback_name_change(this.on_name_change_callback);
- handle.callback_status_message(this.on_status_message_callback);
- handle.callback_user_status(this.on_user_status_callback);
- handle.callback_read_receipt(this.on_read_receipt_callback);
- handle.callback_connection_status(this.on_connection_status_callback);
- handle.callback_typing_change(this.on_typing_change_callback);
-
- // Groupchat callbacks
- handle.callback_group_invite(this.on_group_invite_callback);
- handle.callback_group_message(this.on_group_message_callback);
- handle.callback_group_action(this.on_group_action_callback);
- handle.callback_group_namelist_change(this.on_group_namelist_change_callback);
-
- // File sending callbacks
- handle.callback_file_send_request(this.on_file_sendrequest_callback);
- handle.callback_file_control(this.on_file_control_callback);
- handle.callback_file_data(this.on_file_data_callback);
- }
-
- private void init_contact_list() {
- int[] friend_numbers;
- uint ret = 0;
- uint count_friendlist = 0;
- lock(handle) {
- count_friendlist = handle.count_friendlist();
- friend_numbers = new int[count_friendlist];
- ret = handle.get_friendlist(friend_numbers);
- }
- if(ret != count_friendlist)
- return;
- _contacts.remove_all();
- _groups.remove_all();
- for(int i = 0; i < friend_numbers.length; ++i) {
- int friend_id = friend_numbers[i];
- uint8[] friend_key = get_client_id(friend_id);
- Contact c = new Contact(friend_key, friend_id);
- c.name = get_name(friend_id);
- c.status_message = get_status_message(friend_id);
- uint64 last_seen = get_last_online(friend_id);
- if(last_seen > 0) {
- c.last_seen = new DateTime.from_unix_local((int64)last_seen);
- }
- contact_storage.load_contact_data(c);
- _contacts.set(friend_id, c);
- };
- }
-
- ////////////////////////////// Callbacks /////////////////////////////////////////
- private void on_friend_request_callback(Tox.Tox tox, uint8[] public_key, uint8[] data)
- requires (public_key != null)
- requires (data != null)
- {
- string message = Tools.uint8_to_nullterm_string(data);
- uint8[] public_key_clone = new uint8[Tox.CLIENT_ID_SIZE];
- Memory.copy(public_key_clone, public_key, Tox.CLIENT_ID_SIZE);
- Idle.add(() => {
- Contact contact = new Contact(public_key_clone, -1);
- on_friend_request(contact, message);
- return false;
- });
- }
-
- private void on_friend_message_callback(Tox.Tox tox, int friend_number, uint8[] message)
- requires(message != null)
- {
- string message_string = Tools.uint8_to_nullterm_string(message);
- Idle.add(() => {
- on_friend_message(_contacts.get(friend_number), message_string);
- return false;
- });
- }
-
- private void on_friend_action_callback(Tox.Tox tox, int32 friend_number, uint8[] action)
- requires(action != null)
- {
- string action_string = Tools.uint8_to_nullterm_string(action);
- Idle.add(() => {
- on_friend_action(_contacts.get(friend_number), action_string);
- return false;
- });
- }
-
- private void on_name_change_callback(Tox.Tox tox, int32 friend_number, uint8[] new_name)
- requires(new_name != null)
- {
- string new_name_dup = Tools.uint8_to_nullterm_string(new_name);
- Idle.add(() => {
- Contact contact = _contacts.get(friend_number);
- string old_name = contact.name;
- contact.name = new_name_dup;
- on_name_change(contact, old_name);
- return false;
- });
- }
-
- private void on_status_message_callback(Tox.Tox tox, int32 friend_number, uint8[] status)
- requires(status != null)
- {
- string status_dup = Tools.uint8_to_nullterm_string(status);
- Idle.add(() => {
- Contact contact = _contacts.get(friend_number);
- string old_status = contact.status_message;
- contact.status_message = status_dup;
- on_status_message(contact, old_status);
- return false;
- });
- }
-
- private void on_user_status_callback(Tox.Tox tox, int32 friend_number, uint8 user_status) {
- Idle.add(() => {
- Contact contact = _contacts.get(friend_number);
- uint8 old_status = contact.user_status;
- contact.user_status = user_status;
- on_user_status(contact, old_status);
- return false;
- });
- }
-
- private void on_read_receipt_callback(Tox.Tox tox, int32 friend_number, uint32 receipt) {
- Idle.add(() => {
- on_read_receipt(_contacts.get(friend_number), receipt);
- return false;
- });
- }
-
- private void on_connection_status_callback(Tox.Tox tox, int32 friend_number, uint8 status) {
- Idle.add(() => {
- Contact contact = _contacts.get(friend_number);
- contact.online = (status != 0);
- contact.last_seen = new DateTime.now_local();
-
- if(status == 0) {
- contact.get_filetransfers().for_each((id, ft) => {
- if(ft.status == FileTransferStatus.PENDING || ft.status == FileTransferStatus.IN_PROGRESS || ft.status == FileTransferStatus.PAUSED) {
- ft.status = (ft.direction == FileTransferDirection.INCOMING) ? FileTransferStatus.RECEIVING_BROKEN : FileTransferStatus.SENDING_BROKEN;
- }
- });
- } else {
- contact.get_filetransfers().for_each((id, ft) => {
- if(ft.status == FileTransferStatus.RECEIVING_BROKEN) {
- lock(handle) {
- uint64[] data = {ft.bytes_processed};
- handle.file_send_control(friend_number, 1, id, Tox.FileControlStatus.RESUME_BROKEN, (uint8[])data);
- }
- }
- });
- }
-
- on_connection_status(contact);
- return false;
- });
- }
-
- private void on_typing_change_callback(Tox.Tox tox, int32 friend_number, uint8 is_typing) {
- Contact contact = _contacts.get(friend_number);
- contact.is_typing = is_typing != 0;
- Idle.add(() => {
- on_typing_change(contact, is_typing != 0);
- return false;
- });
- }
-
- // Group chat callbacks
- private void on_group_invite_callback(Tox.Tox tox, int32 friendnumber, uint8[] group_public_key)
- requires(group_public_key != null)
- {
- uint8[] group_public_key_clone = new uint8[Tox.CLIENT_ID_SIZE];
- Memory.copy(group_public_key_clone, group_public_key, Tox.CLIENT_ID_SIZE);
- Idle.add(() => {
- on_group_invite(_contacts.get(friendnumber), new GroupChat(group_public_key_clone));
- return false;
- });
- }
-
- private void on_group_message_callback(Tox.Tox tox, int groupnumber, int friendgroupnumber, uint8[] message)
- requires(message != null)
- {
- string message_string = Tools.uint8_to_nullterm_string(message);
- Idle.add(() => {
- on_group_message(_groups.get(groupnumber), friendgroupnumber, message_string);
- return false;
- });
- }
-
- private void on_group_action_callback(Tox.Tox tox, int groupnumber, int friendgroupnumber, uint8[] action)
- requires(action != null)
- {
- string action_string = Tools.uint8_to_nullterm_string(action);
- Idle.add(() => {
- on_group_action(_groups.get(groupnumber), friendgroupnumber, action_string);
- return false;
- });
- }
-
- private void on_group_namelist_change_callback(Tox.Tox tox, int groupnumber, int peernumber, Tox.ChatChange change) {
-/*
- string chat_change_string = "";
- if(change == Tox.ChatChange.PEER_ADD) {
- chat_change_string = "ADD";
- } else if (change == Tox.ChatChange.PEER_DEL) {
- chat_change_string = "DEL";
- } else {
- chat_change_string = "NAME";
- }
- stdout.printf(_("[gnc] <%s> [%i] #%i\n"), chat_change_string, peernumber, groupnumber);
-*/
- Idle.add(() => {
- GroupChat g = _groups.get(groupnumber);
- if(change == Tox.ChatChange.PEER_ADD) {
- GroupChatContact c = new GroupChatContact(peernumber);
- g.peers.set(peernumber, c);
- g.peer_count++;
- } else if (change == Tox.ChatChange.PEER_DEL) {
- if(!g.peers.remove(peernumber)) {
- Logger.log(LogLevel.ERROR, "Could not remove peer [%i] from groupchat #%i (no such peer)".printf(peernumber, groupnumber));
- }
- g.peer_count--;
- } else { // change == PEER_NAME
- g.peers.get(peernumber).name = group_peername(g, peernumber);
- }
- on_group_peer_changed(g, peernumber, change);
- return false;
- });
- }
-
- //File sending callbacks
- private void on_file_sendrequest_callback(Tox.Tox tox, int32 friendnumber, uint8 filenumber, uint64 filesize, uint8[] filename)
- requires(filename != null)
- {
- string filename_dup = Tools.uint8_to_nullterm_string(filename);
- Idle.add(() => {
- string filename_str = File.new_for_path(filename_dup).get_basename();
- on_file_sendrequest(friendnumber, filenumber, filesize, filename_str);
- return false;
- });
- }
-
- private void on_file_control_callback(Tox.Tox tox, int32 friendnumber, uint8 receive_send, uint8 filenumber, uint8 status, uint8[] data) {
- uint8[] data_clone = new uint8[data.length];
- Memory.copy(data_clone, data, data.length);
- Idle.add(() => {
- on_file_control(friendnumber, filenumber, receive_send, status, data_clone);
- return false;
- });
- }
-
- private void on_file_data_callback(Tox.Tox tox, int32 friendnumber, uint8 filenumber, uint8[] data)
- requires(data != null)
- {
- uint8[] data_clone = new uint8[data.length];
- Memory.copy(data_clone, data, data.length);
- Idle.add(() => {
- on_file_data(friendnumber, filenumber, data_clone);
- return false;
- });
- }
-
- ////////////////////////// Misc functions //////////////////////////////////
-
- public void save_extended_contact_data(Contact c) {
- contact_storage.save_contact_data(c);
- }
-
- public void load_extended_contact_data(Contact c) {
- contact_storage.load_contact_data(c);
- }
-
- ///////////////////////// Wrapper functions ////////////////////////////////
-
- // Add a friend, returns Tox.FriendAddError on error and friend_number on success
- public Tox.FriendAddError add_friend(Contact c, string message)
- requires(c != null)
- requires(c.public_key.length == Tox.FRIEND_ADDRESS_SIZE)
- requires(message != null)
- {
- Tox.FriendAddError ret = Tox.FriendAddError.UNKNOWN;
-
- lock(handle) {
- ret = handle.add_friend(c.public_key, message.data);
- }
-
- if(ret < 0)
- return ret;
- uint8[] client_key = new uint8[Tox.CLIENT_ID_SIZE];
- Memory.copy(client_key, c.public_key, Tox.CLIENT_ID_SIZE);
- c.public_key = client_key;
- c.friend_id = (int)ret;
- _contacts.set((int)ret, c);
- return ret;
- }
-
- public int add_friend_norequest(Contact c)
- requires(c != null)
- {
- int ret = -1;
-
- if(c.public_key.length != Tox.CLIENT_ID_SIZE)
- return ret;
-
- lock(handle) {
- ret = handle.add_friend_norequest(c.public_key);
- }
- if(ret >= 0) {
- c.friend_id = ret;
- _contacts.set(ret, c);
- }
- return ret;
- }
-
- public bool join_groupchat(Contact c, GroupChat g)
- requires(c != null)
- requires(g != null)
- {
- int ret = -1;
- lock(handle) {
- ret = handle.join_groupchat(c.friend_id, g.public_key);
- }
- if(ret < 0) {
- return false;
- }
- g.group_id = ret;
- _groups.set(ret, g);
- return true;
- }
-
- public GroupChat? add_groupchat() {
- int ret = -1;
- lock(handle) {
- ret = handle.add_groupchat();
- }
- if(ret < 0)
- return null;
- GroupChat g = new GroupChat.from_id(ret);
- _groups.set(ret, g);
- return g;
- }
-
- public bool del_friend(Contact c)
- requires(c != null)
- {
- int ret = -1;
- lock(handle) {
- ret = handle.del_friend(c.friend_id);
- }
- if(ret == 0) {
- _contacts.remove(c.friend_id);
- }
- return ret == 0;
- }
-
- public bool del_groupchat(GroupChat g)
- requires(g != null)
- {
- int ret = -1;
- lock(handle) {
- ret = handle.del_groupchat(g.group_id);
- }
- if(ret == 0) {
- _groups.remove(g.group_id);
- }
- return ret == 0;
- }
-
- public int invite_friend(Contact c, GroupChat g) {
- lock(handle){
- return handle.invite_friend(c.friend_id, g.group_id);
- }
- }
-
- public string group_peername(GroupChat g, int peernumber)
- requires(g != null)
- {
- uint8[] buf = new uint8[Tox.MAX_NAME_LENGTH + 1];
- lock(handle) {
- handle.group_peername(g.group_id, peernumber, buf);
- }
- return (string)buf;
- }
-
- public int group_number_peers(GroupChat g)
- requires(g != null)
- {
- lock(handle) {
- return handle.group_number_peers(g.group_id);
- }
- }
-
- // Set user status, returns true on success
- public bool set_user_status(UserStatus user_status) {
- int ret = -1;
- lock(handle) {
- ret = handle.set_user_status((Tox.UserStatus)user_status);
- }
- if(ret != 0)
- return false;
- on_own_user_status(user_status);
- return true;
- }
-
- // Set user statusmessage, returns true on success
- public bool set_status_message(string message)
- requires(message != null)
- {
- int ret = -1;
- lock(handle) {
- ret = handle.set_status_message(message.data);
- }
- return ret == 0;
- }
-
- public string get_self_status_message() {
- uint8[] buf = new uint8[Tox.MAX_STATUSMESSAGE_LENGTH + 1];
- int ret = 0;
- lock(handle) {
- ret = handle.get_self_status_message(buf);
- }
- return (string)buf;
- }
-
- // get personal id
- public uint8[] get_address() {
- uint8[] buf = new uint8[Tox.FRIEND_ADDRESS_SIZE];
- lock(handle) {
- handle.get_address(buf);
- }
- return buf;
- }
-
- // set username
- public bool set_name(string name)
- requires(name != null)
- {
- int ret = -1;
- lock(handle) {
- ret = handle.set_name(name.data);
- }
- return ret == 0;
- }
-
- public string get_self_name() {
- uint8[] buf = new uint8[Tox.MAX_NAME_LENGTH + 1];
- int ret = -1;
- lock(handle) {
- ret = handle.get_self_name(buf);
- }
- return (string)buf;
- }
-
- public uint8[] get_client_id(int friend_id) {
- uint8[] buf = new uint8[Tox.CLIENT_ID_SIZE];
- int ret = -1;
- lock(handle) {
- ret = handle.get_client_id(friend_id, buf);
- }
- return (ret != 0) ? null : buf;
- }
-
- public string? get_name(int friend_number) {
- uint8[] buf = new uint8[Tox.MAX_NAME_LENGTH + 1];
- int ret = -1;
- lock(handle) {
- ret = handle.get_name(friend_number, buf);
- }
- return (ret < 0) ? null: (string)buf;
- }
-
- public string get_status_message(int friend_number) {
- int size = 0;
- int ret = 0;
- uint8 [] buf;
- lock(handle) {
- size = handle.get_status_message_size(friend_number);
- buf = new uint8[size + 1];
- ret = handle.get_status_message(friend_number, buf);
- }
- return (string)buf;
- }
-
- public uint64 get_last_online(int friendnumber) {
- lock(handle) {
- return handle.get_last_online(friendnumber);
- }
- }
-
- public uint32 send_message(int friend_number, string message)
- requires(message != null)
- {
- lock(handle) {
- return handle.send_message(friend_number, message.data);
- }
- }
-
- public uint32 send_action(int friend_number, string action)
- requires(action != null)
- {
- lock(handle) {
- return handle.send_action(friend_number, action.data);
- }
- }
-
- public uint32 group_message_send(int groupnumber, string message)
- requires(message != null)
- {
- lock(handle) {
- return handle.group_message_send(groupnumber, message.data);
- }
- }
-
- public uint32 group_action_send(int groupnumber, string action)
- requires(action != null)
- {
- lock(handle) {
- return handle.group_action_send(groupnumber, action.data);
- }
- }
-
- public bool set_user_is_typing(int friend_number, bool is_typing) {
- lock(handle) {
- return handle.set_user_is_typing(friend_number, is_typing ? 1 : 0) == 0;
- }
- }
-
- public unowned GLib.HashTable get_contact_list() {
- return _contacts;
- }
-
- public unowned GLib.HashTable get_groupchats() {
- return _groups;
- }
-
- public uint8 send_file_request(int friend_number, uint64 file_size, string filename)
- requires(filename != null)
- {
- lock(handle) {
- return (uint8) handle.new_file_sender(friend_number, file_size, filename.data);
- }
- }
-
- public void accept_file (int friendnumber, uint8 filenumber) {
- lock(handle) {
- handle.file_send_control(friendnumber, 1, filenumber, Tox.FileControlStatus.ACCEPT, null);
- }
- }
-
- public void accept_file_resume (int friendnumber, uint8 filenumber) {
- lock(handle) {
- handle.file_send_control(friendnumber, 0, filenumber, Tox.FileControlStatus.ACCEPT, null);
- }
- }
-
- public void reject_file (int friendnumber, uint8 filenumber) {
- lock(handle) {
- handle.file_send_control(friendnumber, 1, filenumber, Tox.FileControlStatus.KILL, null);
- }
- }
-
- public void send_filetransfer_end (int friendnumber, uint8 filenumber) {
- lock(handle) {
- handle.file_send_control(friendnumber, 0, filenumber, Tox.FileControlStatus.FINISHED, null);
- }
- }
-
- public int send_file_data(int friendnumber, uint8 filenumber, uint8[] filedata) {
- lock(handle) {
- return handle.file_send_data(friendnumber, filenumber, filedata);
- }
- }
-
- public int get_recommended_data_size(int friendnumber) {
- lock(handle) {
- return handle.file_data_size(friendnumber);
- }
- }
-
- public uint64 get_remaining_file_data(int friendnumber,uint8 filenumber,uint8 send_receive) {
- lock(handle) {
- return handle.file_data_remaining(friendnumber, filenumber, send_receive);
- }
- }
-
- ////////////////////////////// Thread related operations /////////////////////////
-
- // Background thread main function
- private int run() {
- Logger.log(LogLevel.INFO, "Background thread started.");
-
- if(!bootstrapped) {
- Logger.log(LogLevel.INFO, "Connecting to DHT Nodes:");
- for(int i = 0; i < dht_nodes.length; ++i) {
- // skip ipv6 nodes if we don't support them
- if(dht_nodes[i].is_ipv6 && !ipv6)
- continue;
- Logger.log(LogLevel.INFO, " " + dht_nodes[i].to_string());
- lock(handle) {
- handle.bootstrap_from_address(
- dht_nodes[i].host,
- dht_nodes[i].port,
- dht_nodes[i].pub_key
- );
- }
- }
- bootstrapped = true;
- }
-
- bool new_status = false;
- while(running) {
- lock(handle) {
- new_status = (handle.isconnected() != 0);
- }
- if(new_status && !connected) {
- connected = true;
- connected_dht_node = dht_nodes[0];
- Idle.add(() => { on_own_connection_status(true); return false; });
- } else if(!new_status && connected) {
- connected = false;
- Idle.add(() => { on_own_connection_status(false); return false; });
- }
- lock(handle) {
- handle.do();
- }
- Thread.usleep(handle.do_interval() * 1000);
- }
- Logger.log(LogLevel.INFO, "Background thread stopped.");
- return 0;
- }
-
- // Start the background thread
- public void start() {
- if(running)
- return;
- running = true;
- session_thread = new GLib.Thread("toxbgthread", this.run);
- }
-
- // Stop background thread
- public void stop() {
- running = false;
- connected = false;
- on_own_connection_status(false);
- }
-
- // Wait for background thread to finish
- public int join() {
- if(session_thread != null)
- return session_thread.join();
- return -1;
- }
-
- ////////////////////////////// Load/Save of messenger data /////////////////////////
- public void load_from_file(string filename) throws IOError, Error
- requires(filename != null)
- {
- File f = File.new_for_path(filename);
- if(!f.query_exists())
- throw new IOError.NOT_FOUND(_("File \"%d\" does not exist.").printf(filename));
- FileInfo file_info = f.query_info("*", FileQueryInfoFlags.NONE);
- int64 size = file_info.get_size();
- var data_stream = new DataInputStream(f.read());
- uint8[] buf = new uint8 [size];
-
- if(data_stream.read(buf) != size)
- throw new IOError.FAILED(_("Error while reading from stream."));
- int ret = -1;
- lock(handle) {
- ret = handle.load(buf);
- }
- if(ret != 0)
- throw new IOError.FAILED(_("Error while loading messenger data."));
- init_contact_list();
- message_log.myId = Tools.bin_to_hexstring(get_address());
- }
-
- // Save messenger data from file
- public void save_to_file(string filename) throws IOError, Error
- requires(filename != null)
- {
- File file = File.new_for_path(filename);
- if(!file.query_exists()) {
- Tools.create_path_for_file(filename, 0755);
- }
- DataOutputStream os = new DataOutputStream(file.replace(null, false, FileCreateFlags.PRIVATE | FileCreateFlags.REPLACE_DESTINATION ));
-
- uint32 size = 0;
- uint8[] buf;
-
- lock(handle) {
- size = handle.size();
- buf = new uint8 [size];
- handle.save(buf);
- }
-
- assert(size != 0);
-
- if(os.write(buf) != size)
- throw new IOError.FAILED(_("Error while writing to stream."));
- }
-
- public GLib.List load_history_for_contact(Contact c)
- requires(c != null)
- {
- return message_log.retrieve_history(c);
- }
- }
-}
diff --git a/src/core/UserInfo.vala b/src/core/UserInfo.vala
new file mode 100644
index 0000000..1a4a9d3
--- /dev/null
+++ b/src/core/UserInfo.vala
@@ -0,0 +1,86 @@
+/*
+ * UserInfo.vala
+ *
+ * Copyright (C) 2018 Venom authors and contributors
+ *
+ * This file is part of Venom.
+ *
+ * Venom is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Venom is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Venom. If not, see .
+ */
+
+namespace Venom {
+ public interface UserInfo : GLib.Object {
+ public signal void info_changed();
+
+ public abstract string name { get; set; }
+ public abstract string status_message { get; set; }
+ public abstract Avatar avatar { get; set; }
+ public abstract bool custom_avatar { get; set; }
+ public abstract UserStatus user_status { get; set; }
+ public abstract bool is_connected { get; set; }
+ public abstract string tox_id { get; set; }
+ }
+
+ public class Avatar : GLib.Object {
+ public Gdk.Pixbuf pixbuf { get; set; }
+ public GLib.Bytes hash { get; set; }
+ public Avatar() {
+ reset();
+ }
+
+ public void reset() {
+ pixbuf = pixbuf_from_resource(R.icons.default_contact, 128);
+ hash = new GLib.Bytes(new uint8[] {});
+ }
+
+ public void set_from_data(ILogger logger, uint8[] data, Gdk.Pixbuf? pixbuf = null) throws Error {
+ this.hash = new GLib.Bytes(ToxCore.Tox.hash(data));
+ if (pixbuf != null) {
+ this.pixbuf = pixbuf;
+ } else {
+ var loader = new Gdk.PixbufLoader();
+ try {
+ loader.write(data);
+ loader.close();
+ } catch (Error e) {
+ logger.e("Can not load avatar from data: " + e.message);
+ }
+ unowned Gdk.Pixbuf tmp = loader.get_pixbuf();
+ if (tmp != null) {
+ this.pixbuf = tmp.scale_simple(128, 128, Gdk.InterpType.BILINEAR);
+ }
+ }
+ }
+ }
+
+ public class UserInfoImpl : UserInfo, GLib.Object {
+ public string name { get; set; }
+ public string status_message { get; set; }
+ public Avatar avatar { get; set; }
+ public bool custom_avatar { get; set; }
+ public UserStatus user_status { get; set; }
+ public bool is_connected { get; set; }
+ public string tox_id { get; set; }
+
+ construct {
+ name = R.strings.default_username();
+ status_message = R.strings.default_statusmessage();
+ avatar = new Avatar();
+ custom_avatar = false;
+ user_status = UserStatus.NONE;
+ is_connected = false;
+ tox_id = "";
+ }
+ }
+}
diff --git a/src/core/WidgetFactory.vala b/src/core/WidgetFactory.vala
new file mode 100644
index 0000000..aba0bf0
--- /dev/null
+++ b/src/core/WidgetFactory.vala
@@ -0,0 +1,66 @@
+/*
+ * WidgetFactory.vala
+ *
+ * Copyright (C) 2013-2018 Venom authors and contributors
+ *
+ * This file is part of Venom.
+ *
+ * Venom is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Venom is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Venom. If not, see .
+ */
+
+namespace Venom.Factory {
+ public interface IWidgetFactory : Object {
+ public abstract ApplicationWindow createApplicationWindow(Gtk.Application application,
+ IDhtNodeDatabase node_database, ISettingsDatabase settings_database, IContactDatabase contact_database);
+ public abstract ILogger createLogger();
+ public abstract Gtk.Dialog createAboutDialog();
+ public abstract IDatabaseFactory createDatabaseFactory();
+ public abstract Gtk.Widget createSettingsWidget(ApplicationWindow app_window, ISettingsDatabase database, IDhtNodeDatabase nodeDatabase);
+ }
+
+ public class WidgetFactory : IWidgetFactory, Object {
+ private ILogger logger;
+ private Gtk.Dialog about_dialog;
+
+ public ApplicationWindow createApplicationWindow(Gtk.Application application,
+ IDhtNodeDatabase node_database, ISettingsDatabase settings_database, IContactDatabase contact_database) {
+ return new ApplicationWindow(application, this, node_database, settings_database, contact_database);
+ }
+
+ public ILogger createLogger() {
+ if (logger == null) {
+ logger = new Logger();
+ }
+ return logger;
+ }
+
+ public IDatabaseFactory createDatabaseFactory() {
+ return new SqliteWrapperFactory();
+ }
+
+ public Gtk.Dialog createAboutDialog() {
+ if (about_dialog == null) {
+ about_dialog = new AboutDialog(logger);
+ about_dialog.modal = true;
+ about_dialog.unmap.connect(() => { about_dialog = null; });
+ }
+ return about_dialog;
+ }
+
+ public Gtk.Widget createSettingsWidget(ApplicationWindow app_window, ISettingsDatabase settingsDatabase, IDhtNodeDatabase nodeDatabase) {
+ return new SettingsWidget(createLogger(), app_window, settingsDatabase, nodeDatabase);
+ }
+ }
+
+}
diff --git a/src/testing/TestDns.vala b/src/core/WindowState.vala
similarity index 52%
rename from src/testing/TestDns.vala
rename to src/core/WindowState.vala
index 5e0c651..8727825 100644
--- a/src/testing/TestDns.vala
+++ b/src/core/WindowState.vala
@@ -1,7 +1,7 @@
/*
- * ToxTestDht.vala
+ * WindowState.vala
*
- * Copyright (C) 2013-2014 Venom authors and contributors
+ * Copyright (C) 2018 Venom authors and contributors
*
* This file is part of Venom.
*
@@ -19,25 +19,19 @@
* along with Venom. If not, see .
*/
-namespace Testing {
- public class TestDns : GLib.Object {
- public static int main(string[] args) {
- if(args.length < 2) {
- message("Wrong number of arguments");
- message("Format: %s ", args[0]);
- return -1;
- }
- string pin = args.length < 3 ? null : args[2];
+namespace Venom {
+ public class WindowState : GLib.Object {
+ public int width { get; set; default = 800; }
+ public int height { get; set; default = 600; }
+ public bool is_maximized { get; set; default = false; }
+ public bool is_fullscreen { get; set; default = false; }
- Venom.ToxDns dns = new Venom.ToxDns();
- dns.resolve_id(args[1], () => {
- if(pin == null) {
- stdout.printf("Please insert pin: ");
- pin = stdin.read_line();
- }
- return pin;
- });
- return 0;
+ public static string serialize(WindowState state) throws Error {
+ return Json.gobject_to_data(state, null);
+ }
+
+ public static WindowState deserialize(string data) throws Error {
+ return Json.gobject_from_data(typeof(WindowState), data) as WindowState;
}
}
}
diff --git a/src/db/DatabaseInterfaces.vala b/src/db/DatabaseInterfaces.vala
new file mode 100644
index 0000000..829c051
--- /dev/null
+++ b/src/db/DatabaseInterfaces.vala
@@ -0,0 +1,138 @@
+/*
+ * DatabaseInterfaces.vala
+ *
+ * Copyright (C) 2017 Venom authors and contributors
+ *
+ * This file is part of Venom.
+ *
+ * Venom is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Venom is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Venom. If not, see .
+ */
+
+namespace Venom {
+ public interface ISettingsDatabase : Object {
+ public abstract bool enable_dark_theme { get; set; }
+ public abstract bool enable_animations { get; set; }
+ public abstract bool enable_logging { get; set; }
+ public abstract bool enable_urgency_notification { get; set; }
+ public abstract bool enable_tray { get; set; }
+ public abstract bool enable_notify { get; set; }
+ public abstract bool enable_infinite_log { get; set; }
+ public abstract bool enable_send_typing { get; set; }
+ public abstract int days_to_log { get; set; }
+ public abstract bool enable_proxy { get; set; }
+ public abstract bool enable_custom_proxy { get; set; }
+ public abstract string custom_proxy_host { get; set; }
+ public abstract int custom_proxy_port { get; set; }
+ public abstract bool enable_udp { get; set; }
+ public abstract bool enable_ipv6 { get; set; }
+ public abstract bool enable_local_discovery { get; set; }
+ public abstract bool enable_hole_punching { get; set; }
+
+ public abstract void load();
+ public abstract void save();
+ }
+
+ public interface IDhtNodeDatabase : Object {
+ public abstract void insertDhtNode(string key, string address, uint port, bool isBlocked, string owner, string location);
+ public abstract List getDhtNodes(IDhtNodeFactory factory);
+ public abstract void deleteDhtNode(string key);
+ }
+
+ public interface IDhtNodeFactory : Object {
+ public abstract IDhtNode createDhtNode(string key, string address, uint port, bool blocked, string owner, string location);
+ }
+
+ public interface ILoggedMessage : Object {}
+
+ public interface ILoggedMessageFactory : Object {
+ public abstract ILoggedMessage createLoggedMessage(string userId, string contactId, string message, DateTime time, bool outgoing);
+ }
+
+ public interface IMessageDatabase : Object {
+ public abstract void insertMessage(string userId, string contactId, string message, DateTime time, bool outgoing);
+ public abstract List retrieveMessages(string userId, string contactId, ILoggedMessageFactory messageFactory);
+ public abstract void deleteMessagesBefore(DateTime date);
+ }
+
+ public interface IContactDatabase : Object {
+ public abstract void loadContactData(string userId, IContactData contactData);
+ public abstract void saveContactData(string userId, string note, string alias, bool isBlocked, string group);
+ public abstract void deleteContactData(string userId);
+ }
+
+ public interface IContactData : Object {
+ public abstract void saveContactData(string note, string alias, bool isBlocked, string group);
+ }
+
+ public errordomain DatabaseStatementError {
+ PREPARE,
+ STEP,
+ INDEX,
+ BIND
+ }
+
+ public errordomain DatabaseError {
+ OPEN,
+ QUERY
+ }
+
+ public enum DatabaseResult {
+ OK,
+ DONE,
+ ROW,
+ ERROR,
+ ABORT,
+ OTHER
+ }
+
+ public interface IDatabase : Object {
+ }
+
+ public interface IDatabaseStatement : Object {
+ public abstract DatabaseResult step() throws DatabaseStatementError;
+ public abstract void bind_text(string key, string val) throws DatabaseStatementError;
+ public abstract void bind_int64(string key, int64 val) throws DatabaseStatementError;
+ public abstract void bind_int(string key, int val) throws DatabaseStatementError;
+ public abstract void bind_bool(string key, bool val) throws DatabaseStatementError;
+ public abstract string column_text(int key) throws DatabaseStatementError;
+ public abstract int64 column_int64(int key) throws DatabaseStatementError;
+ public abstract int column_int(int key) throws DatabaseStatementError;
+ public abstract bool column_bool(int key) throws DatabaseStatementError;
+ public abstract void reset();
+ public abstract IDatabaseStatementBuilder builder();
+ }
+
+ public interface IDatabaseStatementBuilder : Object {
+ public abstract IDatabaseStatementBuilder step() throws DatabaseStatementError;
+ public abstract IDatabaseStatementBuilder bind_text(string key, string val) throws DatabaseStatementError;
+ public abstract IDatabaseStatementBuilder bind_int64(string key, int64 val) throws DatabaseStatementError;
+ public abstract IDatabaseStatementBuilder bind_int(string key, int val) throws DatabaseStatementError;
+ public abstract IDatabaseStatementBuilder bind_bool(string key, bool val) throws DatabaseStatementError;
+ public abstract IDatabaseStatementBuilder reset();
+ }
+
+ public interface IDatabaseFactory : Object {
+ public abstract IDatabase createDatabase(string path) throws DatabaseError;
+ public abstract IDatabaseStatementFactory createStatementFactory(IDatabase database);
+
+ public abstract IDhtNodeDatabase createNodeDatabase(IDatabaseStatementFactory factory, ILogger logger) throws DatabaseStatementError;
+ public abstract IContactDatabase createContactDatabase(IDatabaseStatementFactory factory, ILogger logger) throws DatabaseStatementError;
+ public abstract IMessageDatabase createMessageDatabase(IDatabaseStatementFactory factory, ILogger logger) throws DatabaseStatementError;
+ public abstract ISettingsDatabase createSettingsDatabase(IDatabaseStatementFactory factory, ILogger logger) throws DatabaseStatementError;
+ }
+
+ public interface IDatabaseStatementFactory : Object {
+ public abstract IDatabaseStatement createStatement(string zSql) throws DatabaseStatementError;
+ }
+}
diff --git a/src/db/SqliteSettingsDatabase.vala b/src/db/SqliteSettingsDatabase.vala
new file mode 100644
index 0000000..b36d2ab
--- /dev/null
+++ b/src/db/SqliteSettingsDatabase.vala
@@ -0,0 +1,218 @@
+/*
+ * SqliteSettingsDatabase.vala
+ *
+ * Copyright (C) 2013-2018 Venom authors and contributors
+ *
+ * This file is part of Venom.
+ *
+ * Venom is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Venom is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Venom. If not, see .
+ */
+
+namespace Venom {
+ public class SqliteSettingsDatabase : ISettingsDatabase, Object {
+ public bool enable_dark_theme { get; set; default = false; }
+ public bool enable_animations { get; set; default = true; }
+ public bool enable_logging { get; set; default = false; }
+ public bool enable_urgency_notification { get; set; default = true; }
+ public bool enable_tray { get; set; default = false; }
+ public bool enable_notify { get; set; default = false; }
+ public bool enable_infinite_log { get; set; default = true; }
+ public bool enable_send_typing { get; set; default = false; }
+ public int days_to_log { get; set; default = 180; }
+ public bool enable_proxy { get; set; default = true; }
+ public bool enable_custom_proxy { get; set; default = false; }
+ public string custom_proxy_host { get; set; default = "localhost"; }
+ public int custom_proxy_port { get; set; default = 9150; }
+ public bool enable_udp { get; set; default = true; }
+ public bool enable_ipv6 { get; set; default = true; }
+ public bool enable_local_discovery { get; set; default = true; }
+ public bool enable_hole_punching { get; set; default = true; }
+
+ private const string CREATE_TABLE_SETTINGS = """
+ CREATE TABLE IF NOT EXISTS Settings (
+ id INTEGER PRIMARY KEY NOT NULL DEFAULT 0,
+ darktheme INTEGER NOT NULL,
+ animations INTEGER NOT NULL,
+ logging INTEGER NOT NULL,
+ urgencynotification INTEGER NOT NULL,
+ tray INTEGER NOT NULL,
+ notify INTEGER NOT NULL,
+ infinitelog INTEGER NOT NULL,
+ sendtyping INTEGER NOT NULL,
+ daystolog INTEGER NOT NULL,
+ enableproxy INTEGER NOT NULL,
+ enablecustomproxy INTEGER NOT NULL,
+ customproxyhost STRING NOT NULL,
+ customproxyport INTEGER NOT NULL,
+ enableudp INTEGER NOT NULL,
+ enableipv6 INTEGER NOT NULL,
+ enablelocaldiscovery INTEGER NOT NULL,
+ enableholepunching INTEGER NOT NULL
+ );
+ """;
+
+ private enum SettingsColumn {
+ ID,
+ DARKTHEME,
+ ANIMATIONS,
+ LOGGING,
+ URGENCYNOTIFICATIONS,
+ TRAY,
+ NOTIFY,
+ INFINITELOG,
+ SENDTYPING,
+ DAYSTOLOG,
+ ENABLE_PROXY,
+ ENABLE_CUSTOM_PROXY,
+ CUSTOM_PROXY_HOST,
+ CUSTOM_PROXY_PORT,
+ ENABLE_UDP,
+ ENABLE_IPV6,
+ ENABLE_LOCAL_DISCOVERY,
+ ENABLE_HOLE_PUNCHING
+ }
+
+ private const string TABLE_ID = "$ID";
+ private const string TABLE_DARKTHEME = "$DARKTHEME";
+ private const string TABLE_ANIMATIONS = "$ANIMATIONS";
+ private const string TABLE_LOGGING = "$LOGGING";
+ private const string TABLE_URGENCYNOTIFICATIONS = "$URGENCYNOTIFICATIONS";
+ private const string TABLE_TRAY = "$TRAY";
+ private const string TABLE_NOTIFY = "$NOTIFY";
+ private const string TABLE_INFINITELOG = "$INFINITELOG";
+ private const string TABLE_SENDTYPING = "$SENDTYPING";
+ private const string TABLE_DAYSTOLOG = "$DAYSTOLOG";
+ private const string TABLE_ENABLE_PROXY = "$PROXY";
+ private const string TABLE_ENABLE_CUSTOM_PROXY = "$CUSTOMPROXY";
+ private const string TABLE_CUSTOM_PROXY_HOST = "$CUSTOMPROXYHOST";
+ private const string TABLE_CUSTOM_PROXY_PORT = "$CUSTOMPROXYPORT";
+ private const string TABLE_UDP = "$UDP";
+ private const string TABLE_IPV6 = "$IPV6";
+ private const string TABLE_LOCAL_DISCOVERY = "$LOCALDISCOVERY";
+ private const string TABLE_HOLE_PUNCHING = "$HOLEPUNCHING";
+
+ private static string STATEMENT_INSERT_SETTINGS =
+ "INSERT OR REPLACE INTO Settings (id, darktheme, animations, logging, urgencynotification, tray, notify, infinitelog, sendtyping, daystolog, enableproxy, enablecustomproxy, customproxyhost, customproxyport, enableudp, enableipv6, enablelocaldiscovery, enableholepunching)"
+ + " VALUES (%s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s);"
+ .printf(TABLE_ID,
+ TABLE_DARKTHEME,
+ TABLE_ANIMATIONS,
+ TABLE_LOGGING,
+ TABLE_URGENCYNOTIFICATIONS,
+ TABLE_TRAY,
+ TABLE_NOTIFY,
+ TABLE_INFINITELOG,
+ TABLE_SENDTYPING,
+ TABLE_DAYSTOLOG,
+ TABLE_ENABLE_PROXY,
+ TABLE_ENABLE_CUSTOM_PROXY,
+ TABLE_CUSTOM_PROXY_HOST,
+ TABLE_CUSTOM_PROXY_PORT,
+ TABLE_UDP,
+ TABLE_IPV6,
+ TABLE_LOCAL_DISCOVERY,
+ TABLE_HOLE_PUNCHING);
+
+ private static string STATEMENT_SELECT_SETTINGS = "SELECT * FROM Settings WHERE id = 0";
+
+ private IDatabaseStatement insertStatement;
+ private IDatabaseStatement selectStatement;
+
+ private ILogger logger;
+
+ private bool initialized = false;
+
+ public SqliteSettingsDatabase(IDatabaseStatementFactory statementFactory, ILogger logger) throws DatabaseStatementError {
+
+ this.logger = logger;
+
+ statementFactory
+ .createStatement(CREATE_TABLE_SETTINGS)
+ .step();
+
+ insertStatement = statementFactory.createStatement(STATEMENT_INSERT_SETTINGS);
+ selectStatement = statementFactory.createStatement(STATEMENT_SELECT_SETTINGS);
+ logger.d("SqliteSettingsDatabase created.");
+ }
+
+ ~SqliteSettingsDatabase() {
+ save();
+ logger.d("SqliteSettingsDatabase destroyed.");
+ }
+
+ public void load() {
+ if (initialized) {
+ save();
+ }
+ initialized = true;
+
+ try {
+ if (selectStatement.step() == DatabaseResult.ROW) {
+ enable_dark_theme = selectStatement.column_bool(SettingsColumn.DARKTHEME);
+ enable_animations = selectStatement.column_bool(SettingsColumn.ANIMATIONS);
+ enable_logging = selectStatement.column_bool(SettingsColumn.LOGGING);
+ enable_urgency_notification = selectStatement.column_bool(SettingsColumn.URGENCYNOTIFICATIONS);
+ enable_tray = selectStatement.column_bool(SettingsColumn.TRAY);
+ enable_notify = selectStatement.column_bool(SettingsColumn.NOTIFY);
+ enable_infinite_log = selectStatement.column_bool(SettingsColumn.INFINITELOG);
+ enable_send_typing = selectStatement.column_bool(SettingsColumn.SENDTYPING);
+ days_to_log = selectStatement.column_int(SettingsColumn.DAYSTOLOG);
+ enable_proxy = selectStatement.column_bool(SettingsColumn.ENABLE_PROXY);
+ enable_custom_proxy = selectStatement.column_bool(SettingsColumn.ENABLE_CUSTOM_PROXY);
+ custom_proxy_host = selectStatement.column_text(SettingsColumn.CUSTOM_PROXY_HOST);
+ custom_proxy_port = selectStatement.column_int(SettingsColumn.CUSTOM_PROXY_PORT);
+ enable_udp = selectStatement.column_bool(SettingsColumn.ENABLE_UDP);
+ enable_ipv6 = selectStatement.column_bool(SettingsColumn.ENABLE_IPV6);
+ enable_local_discovery = selectStatement.column_bool(SettingsColumn.ENABLE_LOCAL_DISCOVERY);
+ enable_hole_punching = selectStatement.column_bool(SettingsColumn.ENABLE_HOLE_PUNCHING);
+ } else {
+ logger.i("No settings entry found.");
+ }
+ } catch (DatabaseStatementError e) {
+ logger.e("Could not retrieve settings from database: " + e.message);
+ } finally {
+ selectStatement.reset();
+ }
+ }
+
+ public void save() {
+ try {
+ insertStatement.builder()
+ .bind_int( TABLE_ID, 0)
+ .bind_bool(TABLE_DARKTHEME, enable_dark_theme)
+ .bind_bool(TABLE_ANIMATIONS, enable_animations)
+ .bind_bool(TABLE_LOGGING, enable_logging)
+ .bind_bool(TABLE_URGENCYNOTIFICATIONS, enable_urgency_notification)
+ .bind_bool(TABLE_TRAY, enable_tray)
+ .bind_bool(TABLE_NOTIFY, enable_notify)
+ .bind_bool(TABLE_INFINITELOG, enable_infinite_log)
+ .bind_bool(TABLE_SENDTYPING, enable_send_typing)
+ .bind_int( TABLE_DAYSTOLOG, days_to_log)
+ .bind_bool(TABLE_ENABLE_PROXY, enable_proxy)
+ .bind_bool(TABLE_ENABLE_CUSTOM_PROXY, enable_custom_proxy)
+ .bind_text(TABLE_CUSTOM_PROXY_HOST, custom_proxy_host)
+ .bind_int(TABLE_CUSTOM_PROXY_PORT, custom_proxy_port)
+ .bind_bool(TABLE_UDP, enable_udp)
+ .bind_bool(TABLE_IPV6, enable_ipv6)
+ .bind_bool(TABLE_LOCAL_DISCOVERY, enable_local_discovery)
+ .bind_bool(TABLE_HOLE_PUNCHING, enable_hole_punching)
+ .step();
+ } catch (DatabaseStatementError e) {
+ logger.e("Could not insert settings into database: " + e.message);
+ } finally {
+ insertStatement.reset();
+ }
+ }
+ }
+}
diff --git a/src/db/SqliteWrapper.vala b/src/db/SqliteWrapper.vala
new file mode 100644
index 0000000..3f50ef7
--- /dev/null
+++ b/src/db/SqliteWrapper.vala
@@ -0,0 +1,189 @@
+/*
+ * SqliteWrapper.vala
+ *
+ * Copyright (C) 2013-2018 Venom authors and contributors
+ *
+ * This file is part of Venom.
+ *
+ * Venom is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Venom is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Venom. If not, see .
+ */
+
+namespace Venom {
+
+ public class SqliteWrapperFactory : IDatabaseFactory, Object {
+ public IDatabase createDatabase(string path) throws DatabaseError {
+ return new SqliteDatabaseWrapper(path);
+ }
+
+ public IDatabaseStatementFactory createStatementFactory(IDatabase database) {
+ return new SqliteStatementFactory(database as SqliteDatabaseWrapper);
+ }
+
+ public IDhtNodeDatabase createNodeDatabase(IDatabaseStatementFactory factory, ILogger logger) throws DatabaseStatementError {
+ return new SqliteDhtNodeDatabase(factory, logger);
+ }
+ public IContactDatabase createContactDatabase(IDatabaseStatementFactory factory, ILogger logger) throws DatabaseStatementError {
+ return new SqliteContactDatabase(factory, logger);
+ }
+ public IMessageDatabase createMessageDatabase(IDatabaseStatementFactory factory, ILogger logger) throws DatabaseStatementError {
+ return new SqliteMessageDatabase(factory, logger);
+ }
+
+ public ISettingsDatabase createSettingsDatabase(IDatabaseStatementFactory factory, ILogger logger) throws DatabaseStatementError {
+ return new SqliteSettingsDatabase(factory, logger);
+ }
+ }
+
+ public class SqliteStatementFactory : IDatabaseStatementFactory, Object {
+ private SqliteDatabaseWrapper database;
+ public SqliteStatementFactory(SqliteDatabaseWrapper database) {
+ this.database = database;
+ }
+
+ public IDatabaseStatement createStatement(string zSql) throws DatabaseStatementError {
+ return new SqliteStatementWrapper(database, zSql);
+ }
+ }
+
+ public class SqliteStatementWrapper : IDatabaseStatement, Object {
+ private Sqlite.Statement statement;
+
+ public SqliteStatementWrapper(SqliteDatabaseWrapper database, string zSql) throws DatabaseStatementError {
+ var result = database.handle.prepare_v2(zSql, zSql.length, out statement);
+ if (result != Sqlite.OK) {
+ throw new DatabaseStatementError.PREPARE("Could not create statement: " + database.handle.errmsg());
+ }
+ }
+
+ public DatabaseResult step() throws DatabaseStatementError {
+ return fromSqlite(checkSqliteStepResult(statement.step()));
+ }
+
+ public void bind_text(string key, string val) throws DatabaseStatementError {
+ var index = statement.bind_parameter_index(key);
+ checkSqliteBindResult(statement.bind_text(index, val));
+ }
+ public void bind_int64(string key, int64 val) throws DatabaseStatementError {
+ var index = statement.bind_parameter_index(key);
+ checkSqliteBindResult(statement.bind_int64(index, val));
+ }
+ public void bind_int(string key, int val) throws DatabaseStatementError {
+ var index = statement.bind_parameter_index(key);
+ checkSqliteBindResult(statement.bind_int(index, val));
+ }
+
+ public void bind_bool(string key, bool val) throws DatabaseStatementError {
+ bind_int(key, val ? 1 : 0);
+ }
+
+ public string column_text(int key) throws DatabaseStatementError {
+ return statement.column_text(key);
+ }
+ public int64 column_int64(int key) throws DatabaseStatementError {
+ return statement.column_int64(key);
+ }
+ public int column_int(int key) throws DatabaseStatementError {
+ return statement.column_int(key);
+ }
+
+ public bool column_bool(int key) throws DatabaseStatementError {
+ return column_int(key) != 0;
+ }
+
+ private DatabaseResult fromSqlite(int result) {
+ switch (result) {
+ case Sqlite.OK:
+ return DatabaseResult.OK;
+ case Sqlite.DONE:
+ return DatabaseResult.DONE;
+ case Sqlite.ABORT:
+ return DatabaseResult.ABORT;
+ case Sqlite.ERROR:
+ return DatabaseResult.ERROR;
+ case Sqlite.ROW:
+ return DatabaseResult.ROW;
+ }
+ return DatabaseResult.OTHER;
+ }
+
+ private int checkSqliteBindResult(int result) throws DatabaseStatementError {
+ if (result != Sqlite.OK) {
+ throw new DatabaseStatementError.BIND("Could not bind statement: " + result.to_string());
+ }
+ return result;
+ }
+
+ private int checkSqliteStepResult(int result) throws DatabaseStatementError {
+ if (result != Sqlite.DONE && result != Sqlite.ROW) {
+ throw new DatabaseStatementError.STEP("Could not step statement: " + result.to_string());
+ }
+ return result;
+ }
+
+ public void reset() {
+ statement.reset();
+ }
+
+ public IDatabaseStatementBuilder builder() {
+ return new Builder(this);
+ }
+
+ public class Builder : IDatabaseStatementBuilder, Object {
+ private IDatabaseStatement statement;
+ public Builder(IDatabaseStatement statement) {
+ this.statement = statement;
+ }
+
+ public IDatabaseStatementBuilder step() throws DatabaseStatementError {
+ statement.step();
+ return this;
+ }
+ public IDatabaseStatementBuilder bind_text(string key, string val) throws DatabaseStatementError {
+ statement.bind_text(key, val);
+ return this;
+ }
+ public IDatabaseStatementBuilder bind_int64(string key, int64 val) throws DatabaseStatementError {
+ statement.bind_int64(key, val);
+ return this;
+ }
+ public IDatabaseStatementBuilder bind_int(string key, int val) throws DatabaseStatementError {
+ statement.bind_int(key, val);
+ return this;
+ }
+ public IDatabaseStatementBuilder bind_bool(string key, bool val) throws DatabaseStatementError {
+ statement.bind_bool(key, val);
+ return this;
+ }
+ public IDatabaseStatementBuilder reset() {
+ statement.reset();
+ return this;
+ }
+ }
+ }
+
+ public class SqliteDatabaseWrapper : IDatabase, Object {
+ private Sqlite.Database database;
+
+ public Sqlite.Database handle {
+ get { return database; }
+ }
+
+ public SqliteDatabaseWrapper(string path) throws DatabaseError {
+ var result = Sqlite.Database.open_v2(path, out database);
+ if (result != Sqlite.OK) {
+ throw new DatabaseError.OPEN("Cannot open sqlite database: " + database.errmsg());
+ }
+ }
+ }
+}
diff --git a/src/icons/icons.gresource.xml b/src/icons/icons.gresource.xml
new file mode 100644
index 0000000..38abb64
--- /dev/null
+++ b/src/icons/icons.gresource.xml
@@ -0,0 +1,12 @@
+
+
+
+ scalable/apps/venom-symbolic.svg
+ scalable/status/busy-symbolic.svg
+ scalable/status/idle-symbolic.svg
+ scalable/status/offline-symbolic.svg
+ scalable/status/online-symbolic.svg
+ scalable/status/conference-symbolic.svg
+ scalable/status/friend-symbolic.svg
+
+
diff --git a/src/icons/scalable/apps/venom-symbolic.svg b/src/icons/scalable/apps/venom-symbolic.svg
new file mode 100644
index 0000000..46b6996
--- /dev/null
+++ b/src/icons/scalable/apps/venom-symbolic.svg
@@ -0,0 +1,11 @@
+
+
diff --git a/src/icons/scalable/status/busy-symbolic.svg b/src/icons/scalable/status/busy-symbolic.svg
new file mode 100644
index 0000000..6b46618
--- /dev/null
+++ b/src/icons/scalable/status/busy-symbolic.svg
@@ -0,0 +1,11 @@
+
+
diff --git a/src/icons/scalable/status/conference-symbolic.svg b/src/icons/scalable/status/conference-symbolic.svg
new file mode 100644
index 0000000..decf3b1
--- /dev/null
+++ b/src/icons/scalable/status/conference-symbolic.svg
@@ -0,0 +1,4 @@
+
+
diff --git a/src/icons/scalable/status/friend-symbolic.svg b/src/icons/scalable/status/friend-symbolic.svg
new file mode 100644
index 0000000..3dfa6f5
--- /dev/null
+++ b/src/icons/scalable/status/friend-symbolic.svg
@@ -0,0 +1,5 @@
+
+
+
diff --git a/src/icons/scalable/status/idle-symbolic.svg b/src/icons/scalable/status/idle-symbolic.svg
new file mode 100644
index 0000000..b241d8f
--- /dev/null
+++ b/src/icons/scalable/status/idle-symbolic.svg
@@ -0,0 +1,12 @@
+
+
+
diff --git a/src/icons/scalable/status/offline-symbolic.svg b/src/icons/scalable/status/offline-symbolic.svg
new file mode 100644
index 0000000..f1f00ea
--- /dev/null
+++ b/src/icons/scalable/status/offline-symbolic.svg
@@ -0,0 +1,11 @@
+
+
diff --git a/src/icons/scalable/status/online-symbolic.svg b/src/icons/scalable/status/online-symbolic.svg
new file mode 100644
index 0000000..69838cc
--- /dev/null
+++ b/src/icons/scalable/status/online-symbolic.svg
@@ -0,0 +1,11 @@
+
+
diff --git a/src/meson.build b/src/meson.build
new file mode 100644
index 0000000..1ccf13d
--- /dev/null
+++ b/src/meson.build
@@ -0,0 +1,123 @@
+vapi_dir = join_paths(meson.current_source_dir(), 'vapi')
+
+add_project_arguments(['--vapidir', vapi_dir], language: 'vala')
+add_project_arguments('-DGETTEXT_PACKAGE="@0@"'.format(meson.project_name()), language: 'c')
+
+gtk_dep = dependency('gtk+-3.0')
+gdk_dep = dependency('gdk-3.0')
+gio_dep = dependency('gio-2.0')
+glib_dep = dependency('glib-2.0')
+gee_dep = dependency('gee-0.8')
+gmodule_dep = dependency('gmodule-2.0')
+sqlite_dep = dependency('sqlite3')
+json_dep = dependency('json-glib-1.0')
+soup_dep = dependency('libsoup-2.4')
+tox_dep = dependency('toxcore')
+gst_dep = dependency('gstreamer-1.0', required : false)
+posix_dep = valac.find_library('posix', required : false)
+
+config_vapi = valac.find_library('config', dirs: vapi_dir)
+config_dep = declare_dependency(dependencies: [config_vapi], include_directories : include_directories('.'))
+configure_file(output : 'config.h', configuration : conf_data)
+
+venom_ui_resources = gnome.compile_resources('venom_ui_resources', 'ui/venom.gresource.xml',
+ source_dir : 'ui',
+ c_name : 'c_venom_ui_res')
+
+venom_icons_resources = gnome.compile_resources('venom_icons_resources', 'icons/icons.gresource.xml',
+ source_dir : 'icons',
+ c_name : 'c_venom_icons_res')
+
+venom_source = files(
+ 'core/Application.vala',
+ 'core/Contact.vala',
+ 'core/FileIO.vala',
+ 'core/FileTransfer.vala',
+ 'core/Interfaces.vala',
+ 'core/Logger.vala',
+ 'core/Message.vala',
+ 'core/NotificationListener.vala',
+ 'core/ObservableList.vala',
+ 'core/R.vala',
+ 'core/TimeStamp.vala',
+ 'core/Tools.vala',
+ 'core/WidgetFactory.vala',
+ 'core/WindowState.vala',
+ 'core/UserInfo.vala',
+ 'db/DatabaseInterfaces.vala',
+ 'db/SqliteSettingsDatabase.vala',
+ 'db/SqliteWrapper.vala',
+ 'plugin/Plugin.vala',
+ 'plugin/Pluginregistrar.vala',
+ 'portal/Request.vala',
+ 'portal/Screenshot.vala',
+ 'tox/Conference.vala',
+ 'tox/ConferenceMessage.vala',
+ 'tox/ContactDatabase.vala',
+ 'tox/DhtNode.vala',
+ 'tox/DhtNodeDatabase.vala',
+ 'tox/FriendRequest.vala',
+ 'tox/JsonWebDhtNodeDatabase.vala',
+ 'tox/MessageDatabase.vala',
+ 'tox/SqliteDhtNodeDatabase.vala',
+ 'tox/ToxAdapterConferenceListener.vala',
+ 'tox/ToxAdapterFriendListener.vala',
+ 'tox/ToxAdapterFiletransferListener.vala',
+ 'tox/ToxAdapterSelfListener.vala',
+ 'tox/ToxContact.vala',
+ 'tox/ToxSession.vala',
+ 'tox/ToxSessionIO.vala',
+ 'tox/ToxSessionThread.vala',
+ 'undo/SimpleUndoStack.vala',
+ 'undo/TextBufferUndoBinding.vala',
+ 'undo/UndoCommand.vala',
+ 'undo/UndoStack.vala',
+ 'view/AboutDialog.vala',
+ 'view/AddContactWidget.vala',
+ 'view/ApplicationWindow.vala',
+ 'view/ConferenceInfoWidget.vala',
+ 'view/ConferenceInviteEntry.vala',
+ 'view/ConferenceWindow.vala',
+ 'view/ContactListEntry.vala',
+ 'view/ContactListRequestEntry.vala',
+ 'view/ContactListWidget.vala',
+ 'view/ContextStyleBinding.vala',
+ 'view/ConversationWindow.vala',
+ 'view/CreateGroupchatWidget.vala',
+ 'view/FileTransferEntry.vala',
+ 'view/FileTransferEntryInline.vala',
+ 'view/FileTransferWidget.vala',
+ 'view/FriendInfoWidget.vala',
+ 'view/FriendRequestWidget.vala',
+ 'view/MessageWidget.vala',
+ 'view/NodeWidget.vala',
+ 'view/PeerEntry.vala',
+ 'view/SettingsWidget.vala',
+ 'view/UserInfoWidget.vala',
+ 'view/WelcomeWidget.vala',
+ 'viewmodel/AddContactViewModel.vala',
+ 'viewmodel/ConferenceInfoViewModel.vala',
+ 'viewmodel/ContactListEntryViewModel.vala',
+ 'viewmodel/ContactListViewModel.vala',
+ 'viewmodel/CreateGroupchatViewModel.vala',
+ 'viewmodel/FileTransferEntryViewModel.vala',
+ 'viewmodel/FriendInfoViewModel.vala',
+ 'viewmodel/MessageViewModel.vala',
+ 'viewmodel/UserInfoViewModel.vala'
+ )
+
+venom_deps = [gtk_dep, gio_dep, gmodule_dep, gee_dep, sqlite_dep, json_dep, tox_dep, config_dep, soup_dep]
+
+venom_lib = static_library('venom', [venom_source, venom_ui_resources, venom_icons_resources],
+ dependencies : venom_deps
+ )
+
+venom_dep = declare_dependency(
+ dependencies : venom_deps,
+ link_with : venom_lib
+ )
+
+venom_binary = executable('venom', ['Main.vala', venom_ui_resources, venom_icons_resources],
+ dependencies : venom_dep,
+ install : true
+ )
diff --git a/src/pixmaps/button_icons/arrow_medgrey.png b/src/pixmaps/button_icons/arrow_medgrey.png
deleted file mode 100644
index 0cbf8aa..0000000
Binary files a/src/pixmaps/button_icons/arrow_medgrey.png and /dev/null differ
diff --git a/src/pixmaps/button_icons/arrow_white.png b/src/pixmaps/button_icons/arrow_white.png
deleted file mode 100644
index e607035..0000000
Binary files a/src/pixmaps/button_icons/arrow_white.png and /dev/null differ
diff --git a/src/pixmaps/button_icons/attach.png b/src/pixmaps/button_icons/attach.png
deleted file mode 100644
index 43a4fd1..0000000
Binary files a/src/pixmaps/button_icons/attach.png and /dev/null differ
diff --git a/src/pixmaps/button_icons/call.png b/src/pixmaps/button_icons/call.png
deleted file mode 100644
index beedcef..0000000
Binary files a/src/pixmaps/button_icons/call.png and /dev/null differ
diff --git a/src/pixmaps/button_icons/check.png b/src/pixmaps/button_icons/check.png
deleted file mode 100644
index 117b86b..0000000
Binary files a/src/pixmaps/button_icons/check.png and /dev/null differ
diff --git a/src/pixmaps/button_icons/emoticon.png b/src/pixmaps/button_icons/emoticon.png
deleted file mode 100644
index 796016e..0000000
Binary files a/src/pixmaps/button_icons/emoticon.png and /dev/null differ
diff --git a/src/pixmaps/button_icons/no.png b/src/pixmaps/button_icons/no.png
deleted file mode 100644
index 14d3d31..0000000
Binary files a/src/pixmaps/button_icons/no.png and /dev/null differ
diff --git a/src/pixmaps/button_icons/pause.png b/src/pixmaps/button_icons/pause.png
deleted file mode 100644
index 567b8e0..0000000
Binary files a/src/pixmaps/button_icons/pause.png and /dev/null differ
diff --git a/src/pixmaps/button_icons/sendmessage.png b/src/pixmaps/button_icons/sendmessage.png
deleted file mode 100644
index b3334e2..0000000
Binary files a/src/pixmaps/button_icons/sendmessage.png and /dev/null differ
diff --git a/src/pixmaps/button_icons/video.png b/src/pixmaps/button_icons/video.png
deleted file mode 100644
index 171233d..0000000
Binary files a/src/pixmaps/button_icons/video.png and /dev/null differ
diff --git a/src/pixmaps/contact_list_icons/add.png b/src/pixmaps/contact_list_icons/add.png
deleted file mode 100644
index e5f864b..0000000
Binary files a/src/pixmaps/contact_list_icons/add.png and /dev/null differ
diff --git a/src/pixmaps/contact_list_icons/group.png b/src/pixmaps/contact_list_icons/group.png
deleted file mode 100644
index 33fe23e..0000000
Binary files a/src/pixmaps/contact_list_icons/group.png and /dev/null differ
diff --git a/src/pixmaps/contact_list_icons/settings.png b/src/pixmaps/contact_list_icons/settings.png
deleted file mode 100644
index 9104188..0000000
Binary files a/src/pixmaps/contact_list_icons/settings.png and /dev/null differ
diff --git a/src/pixmaps/contact_list_icons/transfer.png b/src/pixmaps/contact_list_icons/transfer.png
deleted file mode 100644
index 469ddea..0000000
Binary files a/src/pixmaps/contact_list_icons/transfer.png and /dev/null differ
diff --git a/src/pixmaps/status/dot_away.png b/src/pixmaps/status/dot_away.png
deleted file mode 100644
index cd4e961..0000000
Binary files a/src/pixmaps/status/dot_away.png and /dev/null differ
diff --git a/src/pixmaps/status/dot_away_notification.png b/src/pixmaps/status/dot_away_notification.png
deleted file mode 100644
index fffe7ef..0000000
Binary files a/src/pixmaps/status/dot_away_notification.png and /dev/null differ
diff --git a/src/pixmaps/status/dot_busy.png b/src/pixmaps/status/dot_busy.png
deleted file mode 100644
index 0755885..0000000
Binary files a/src/pixmaps/status/dot_busy.png and /dev/null differ
diff --git a/src/pixmaps/status/dot_busy_notification.png b/src/pixmaps/status/dot_busy_notification.png
deleted file mode 100644
index 216e2d7..0000000
Binary files a/src/pixmaps/status/dot_busy_notification.png and /dev/null differ
diff --git a/src/pixmaps/status/dot_idle.png b/src/pixmaps/status/dot_idle.png
deleted file mode 100644
index cb7bf91..0000000
Binary files a/src/pixmaps/status/dot_idle.png and /dev/null differ
diff --git a/src/pixmaps/status/dot_idle_notification.png b/src/pixmaps/status/dot_idle_notification.png
deleted file mode 100644
index 2d79f8b..0000000
Binary files a/src/pixmaps/status/dot_idle_notification.png and /dev/null differ
diff --git a/src/pixmaps/status/dot_online.png b/src/pixmaps/status/dot_online.png
deleted file mode 100644
index 14e1d4a..0000000
Binary files a/src/pixmaps/status/dot_online.png and /dev/null differ
diff --git a/src/pixmaps/status/dot_online_notification.png b/src/pixmaps/status/dot_online_notification.png
deleted file mode 100644
index 783ac22..0000000
Binary files a/src/pixmaps/status/dot_online_notification.png and /dev/null differ
diff --git a/src/pixmaps/user_icons/default_contact.png b/src/pixmaps/user_icons/default_contact.png
deleted file mode 100644
index 11a175d..0000000
Binary files a/src/pixmaps/user_icons/default_contact.png and /dev/null differ
diff --git a/src/pixmaps/user_icons/default_groupchat.png b/src/pixmaps/user_icons/default_groupchat.png
deleted file mode 100644
index ee70299..0000000
Binary files a/src/pixmaps/user_icons/default_groupchat.png and /dev/null differ
diff --git a/src/pixmaps/venom_pixmaps.gresource.xml b/src/pixmaps/venom_pixmaps.gresource.xml
deleted file mode 100644
index fae798f..0000000
--- a/src/pixmaps/venom_pixmaps.gresource.xml
+++ /dev/null
@@ -1,29 +0,0 @@
-
-
-
- button_icons/arrow_medgrey.png
- button_icons/arrow_white.png
- button_icons/attach.png
- button_icons/call.png
- button_icons/check.png
- button_icons/emoticon.png
- button_icons/no.png
- button_icons/pause.png
- button_icons/sendmessage.png
- button_icons/video.png
- contact_list_icons/add.png
- contact_list_icons/group.png
- contact_list_icons/settings.png
- contact_list_icons/transfer.png
- status/dot_away.png
- status/dot_away_notification.png
- status/dot_busy.png
- status/dot_busy_notification.png
- status/dot_idle.png
- status/dot_idle_notification.png
- status/dot_online.png
- status/dot_online_notification.png
- user_icons/default_contact.png
- user_icons/default_groupchat.png
-
-
diff --git a/src/vapi/djbdns.vapi b/src/plugin/Plugin.vala
similarity index 63%
rename from src/vapi/djbdns.vapi
rename to src/plugin/Plugin.vala
index 7400ae4..a5fb85d 100644
--- a/src/vapi/djbdns.vapi
+++ b/src/plugin/Plugin.vala
@@ -1,7 +1,7 @@
/*
- * djbdns.vapi
+ * Plugin.vala
*
- * Copyright (C) 2013-2014 Venom authors and contributors
+ * Copyright (C) 2018 Venom authors and contributors
*
* This file is part of Venom.
*
@@ -19,14 +19,15 @@
* along with Venom. If not, see .
*/
-[CCode (cprefix = "", cheader_filename = "dns.h")]
-namespace DJBDns {
- [CCode (cname = "stralloc", destroy_function = "", has_type_id = false)]
- public struct AllocatedString {
- string s;
- uint len;
- uint a;
+namespace Venom {
+ public enum PluginState {
+ ACTIVE,
+ INACTIVE
+ }
+
+ public interface Plugin : GLib.Object {
+ public abstract PluginState get_state();
+ public abstract void activate(ILogger logger);
+ public abstract void deactiviate(ILogger logger);
}
- [CCode (cname = "dns_txt")]
- public static int dns_txt(out AllocatedString answer, AllocatedString fqdn);
}
diff --git a/src/plugin/Pluginregistrar.vala b/src/plugin/Pluginregistrar.vala
new file mode 100644
index 0000000..6af2105
--- /dev/null
+++ b/src/plugin/Pluginregistrar.vala
@@ -0,0 +1,63 @@
+/*
+ * Pluginregistrar.vala
+ *
+ * Copyright (C) 2018 Venom authors and contributors
+ *
+ * This file is part of Venom.
+ *
+ * Venom is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Venom is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Venom. If not, see .
+ */
+
+namespace Venom {
+ public errordomain PluginError {
+ LOAD
+ }
+
+ class Pluginregistrar : GLib.Object {
+ private string path;
+ private GLib.Type type;
+ private GLib.Module module;
+ private ILogger logger;
+
+ private delegate GLib.Type RegisterPluginFunction(GLib.Module module);
+
+ public Pluginregistrar(ILogger logger, string name) {
+ assert(GLib.Module.supported());
+ this.logger = logger;
+ this.path = GLib.Module.build_path(GLib.Environment.get_variable("PWD"), name);
+ }
+
+ public void load() throws PluginError {
+ logger.d("Loading plugin with path: '%s'".printf(path));
+
+ module = GLib.Module.open(path, GLib.ModuleFlags.BIND_LAZY);
+ if (module == null) {
+ throw new PluginError.LOAD("Opening module at path '%s' failed".printf(path));
+ }
+
+ logger.d("Loaded module: '%s'".printf(module.name()));
+
+ void* function;
+ module.symbol("register_plugin", out function);
+ unowned RegisterPluginFunction register_plugin = (RegisterPluginFunction) function;
+
+ type = register_plugin(module);
+ logger.d("Plugin type: " + type.name());
+ }
+
+ public T new_object () {
+ return GLib.Object.new (type);
+ }
+ }
+}
diff --git a/src/portal/Request.vala b/src/portal/Request.vala
new file mode 100644
index 0000000..6c1f536
--- /dev/null
+++ b/src/portal/Request.vala
@@ -0,0 +1,11 @@
+namespace org.freedesktop.portal {
+ [DBus(name = "org.freedesktop.portal.Request", timeout = 120000)]
+ public interface Request : GLib.Object {
+
+ [DBus(name = "Close")]
+ public abstract void close() throws DBusError, IOError;
+
+ [DBus(name = "Response")]
+ public signal void response(uint response, GLib.HashTable results);
+ }
+}
diff --git a/src/portal/Screenshot.vala b/src/portal/Screenshot.vala
new file mode 100644
index 0000000..a4fc3e0
--- /dev/null
+++ b/src/portal/Screenshot.vala
@@ -0,0 +1,8 @@
+namespace org.freedesktop.portal {
+ [DBus(name = "org.freedesktop.portal.Screenshot", timeout = 120000)]
+ public interface Screenshot : GLib.Object {
+
+ [DBus(name = "Screenshot")]
+ public abstract GLib.ObjectPath screenshot(string parent_window, GLib.HashTable options) throws DBusError, IOError;
+ }
+}
diff --git a/src/testing/CMakeLists.txt b/src/testing/CMakeLists.txt
deleted file mode 100644
index 0893c2b..0000000
--- a/src/testing/CMakeLists.txt
+++ /dev/null
@@ -1,91 +0,0 @@
-#
-# Copyright (C) 2013-2014 Venom authors and contributors
-#
-# This file is part of Venom.
-#
-# Venom is free software: you can redistribute it and/or modify
-# it under the terms of the GNU General Public License as published by
-# the Free Software Foundation, either version 3 of the License, or
-# (at your option) any later version.
-#
-# Venom is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with Venom. If not, see .
-#
-
-VALA_PRECOMPILE( VALA_C_TEST_DHT
- TestDht.vala
- ../core/Tools.vala
- PACKAGES
- gio-2.0
- tox-1.0
- OPTIONS
- --debug
- --vapidir=${CMAKE_SOURCE_DIR}/src/vapi
- CUSTOM_VAPIS
- GENERATE_VAPI
- GENERATE_HEADER
-)
-
-VALA_PRECOMPILE( VALA_C_TEST_DNS
- TestDns.vala
- "../core/Tools.vala"
- "../core/ToxDns.vala"
- PACKAGES
- gio-2.0
- tox-1.0
- djbdns
- OPTIONS
- --debug
- --vapidir=${CMAKE_SOURCE_DIR}/src/vapi
- CUSTOM_VAPIS
- GENERATE_VAPI
- GENERATE_HEADER
-)
-
-VALA_PRECOMPILE( VALA_C_GROUP_BOT
- GroupBot.vala
- ../core/Tools.vala
- PACKAGES
- gio-2.0
- tox-1.0
- OPTIONS
- --debug
- --target-glib=${TARGET_GLIB}
- --vapidir=${CMAKE_SOURCE_DIR}/src/vapi
- CUSTOM_VAPIS
- GENERATE_VAPI
- GENERATE_HEADER
-)
-
-
-ADD_EXECUTABLE( test_dht EXCLUDE_FROM_ALL
- ${VALA_C_TEST_DHT}
-)
-
-ADD_EXECUTABLE( test_dns EXCLUDE_FROM_ALL
- ${VALA_C_TEST_DNS}
-)
-
-ADD_EXECUTABLE( group_bot EXCLUDE_FROM_ALL
- ${VALA_C_GROUP_BOT}
-)
-
-TARGET_LINK_LIBRARIES( test_dht
- ${TOX_LIBRARIES}
- ${GIO_LIBRARIES}
-)
-
-TARGET_LINK_LIBRARIES( test_dns
- ${GIO_LIBRARIES}
- ${DJBDNS_LIBRARIES}
-)
-
-TARGET_LINK_LIBRARIES( group_bot
- ${TOX_LIBRARIES}
- ${GIO_LIBRARIES}
-)
diff --git a/src/testing/ExamplePlugin.vala b/src/testing/ExamplePlugin.vala
new file mode 100644
index 0000000..e07ab12
--- /dev/null
+++ b/src/testing/ExamplePlugin.vala
@@ -0,0 +1,41 @@
+/*
+ * ExamplePlugin.vala
+ *
+ * Copyright (C) 2018 Venom authors and contributors
+ *
+ * This file is part of Venom.
+ *
+ * Venom is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Venom is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Venom. If not, see .
+ */
+
+namespace Venom {
+ public class ExamplePlugin : GLib.Object, Plugin {
+ private const string TAG = "ExamplePlugin";
+
+ public virtual PluginState get_state() {
+ return PluginState.INACTIVE;
+ }
+
+ public virtual void activate(ILogger logger) {
+ logger.i("%s activated.".printf(TAG));
+ }
+ public virtual void deactiviate(ILogger logger) {
+ logger.i("%s deactivated.".printf(TAG));
+ }
+ }
+}
+
+public GLib.Type register_plugin (GLib.Module module) {
+ return typeof (Venom.ExamplePlugin);
+}
diff --git a/src/testing/GroupBot.vala b/src/testing/GroupBot.vala
index 0f7b9e5..8b7b10d 100644
--- a/src/testing/GroupBot.vala
+++ b/src/testing/GroupBot.vala
@@ -1,7 +1,7 @@
/*
* GroupBot.vala
*
- * Copyright (C) 2013-2014 Venom authors and contributors
+ * Copyright (C) 2013-2018 Venom authors and contributors
*
* This file is part of Venom.
*
@@ -19,194 +19,225 @@
* along with Venom. If not, see .
*/
+using ToxCore;
+
namespace Testing {
- public class GroupBot : GLib.Object {
- private delegate void ActionDelegate(string action_string, int friend_number);
- private class ActionWrapper : GLib.Object {
- public ActionDelegate action;
- public ActionWrapper(ActionDelegate action) {
- this.action = action;
+ public class GroupBot : Object {
+ private const string DEFAULT_CHANNEL = "tox-ontopic";
+
+ private Tox tox;
+ private HashTable channels;
+ private Connection connection_status = Connection.NONE;
+ private static bool running = true;
+
+ public GroupBot() {
+ channels = new HashTable(str_hash, str_equal);
+
+ var optionsErr = ErrOptionsNew.OK;
+ var options = new Options(out optionsErr);
+
+ var file = File.new_for_path("groupbot.data");
+ try {
+ uint8[] savedata;
+ file.load_contents(null, out savedata, null);
+ options.set_savedata_data(savedata);
+ options.savedata_type = SaveDataType.TOX_SAVE;
+ } catch (Error e) {
+ stdout.printf("[LOG] Could not read tox savefile: %s\n", e.message);
}
- }
- public const string DEFAULT_CHANNEL = "tox-ontopic";
- private Tox.Tox tox;
- private HashTable channels = new HashTable(str_hash, str_equal);
- private HashTable actions = new HashTable(str_hash, str_equal);
- public GroupBot( bool ipv6 = false ) {
- tox = new Tox.Tox(ipv6 ? 1 : 0);
+
+ var err = ErrNew.OK;
+ tox = new Tox(options, out err);
+ if (err != ErrNew.OK) {
+ stderr.printf("[FTL] Could not create new tox instance: %s\n", err.to_string());
+ assert_not_reached();
+ }
+
tox.callback_friend_request(on_friend_request);
tox.callback_friend_message(on_friend_message);
- tox.callback_group_message(on_groupchat_message);
- tox.callback_group_namelist_change(on_group_namelist_change);
-
- actions.insert("j", new ActionWrapper(on_action_join));
- actions.insert("join", new ActionWrapper(on_action_join));
- actions.insert("h", new ActionWrapper(on_action_help));
- actions.insert("help", new ActionWrapper(on_action_help));
-
+ tox.callback_friend_connection_status(on_friend_connection_status);
+ tox.callback_conference_invite(on_conference_invite);
+ tox.callback_conference_message(on_conference_message);
+
add_channel(DEFAULT_CHANNEL);
}
-
- private int add_channel(string name) {
- int channel_number = tox.add_groupchat();
- if(channel_number < 0) {
- stderr.printf("[ERR] Creating a new channel %s failed.\n", name);
+
+ ~GroupBot() {
+ var file = File.new_for_path("groupbot.data");
+ try {
+ file.replace_contents(tox.get_savedata(), null, false, FileCreateFlags.NONE, null, null);
+ } catch (Error e) {
+ stderr.printf("[ERR] Saving tox session data failed: %s\n", e.message);
+ }
+ }
+
+ private uint32 add_channel(string name) {
+ var err = ErrConferenceNew.OK;
+ var channel_number = tox.conference_new(out err);
+ if (err != ErrConferenceNew.OK) {
+ stderr.printf("[ERR] Creating new channel \"%s\" failed: %s\n", name, err.to_string());
} else {
- stdout.printf("[LOG] Created new channel #%s [%i]\n", name, channel_number);
+ stdout.printf("[LOG] Created new channel #%s [%u]\n", name, channel_number);
channels.set(name, channel_number);
}
return channel_number;
}
- private string get_name(int friend_number) {
- uint8[] name_buf = new uint8[Tox.MAX_NAME_LENGTH];
- if( tox.get_name(friend_number, name_buf) < 0) {
- stderr.printf("[ERR] Could not get name for friend #%i\n", friend_number);
+ private static string get_friend_name(Tox tox, uint32 friend_number) {
+ var err = ErrFriendQuery.OK;
+ var name = tox.friend_get_name(friend_number, out err);
+ if (err != ErrFriendQuery.OK) {
+ stderr.printf("[ERR] Could not query friend name: %s\n", err.to_string());
+ name = "FRIEND #%u".printf(friend_number);
}
- return (string) name_buf;
+ return name;
}
- private void on_action_join(string action_string, int friend_number) {
- string name = get_name(friend_number);
- stdout.printf("[LOG] Join action from %s: /j %s\n", name, action_string);
- string channel = DEFAULT_CHANNEL;
- int channel_number = -1;
-
- if(action_string != "") {
- GLib.Regex channel_regex = null;
- GLib.MatchInfo info = null;
- try {
- channel_regex = new GLib.Regex("^#?(?P[[:alnum:]]+(-[[:alnum:]]+)*)$");
- } catch (GLib.RegexError e) {
- stderr.printf("Can't create action regex: %s.\n", e.message);
- return;
- }
- if( channel_regex.match(action_string, 0, out info) ) {
- string channel_string = info.fetch_named("channel_string");
- if(channel_string != null)
- channel = channel_string;
- } else {
- stdout.printf("[LOG] Join action with invalid channel\n");
- }
- }
-
- if(channels.contains(channel)) {
- channel_number = channels.get(channel);
- } else {
- channel_number = add_channel(channel);
- }
- stdout.printf("[LOG] Inviting '%s' to channel #%s [%i]\n", name, channel, channel_number);
- if(tox.invite_friend(friend_number, channel_number) != 0) {
- stderr.printf("[ERR] Failed to invite '%s' to channel #%s\n", name, channel);
+ private static void on_conference_invite(Tox tox, uint32 friend_number, ConferenceType type, uint8[] cookie, void *user_data) {
+ stdout.printf("[CI ] from %s\n", get_friend_name(tox, friend_number));
+ var err = ErrConferenceJoin.OK;
+ tox.conference_join(friend_number, cookie, out err);
+ if (err != ErrConferenceJoin.OK) {
+ stderr.printf("[ERR] Could not join conference: %s\n", err.to_string());
}
}
-
- private void on_action_help(string action_string, int friend_number) {
- string name = get_name(friend_number);
- stdout.printf("[LOG] Help action from %s: %s\n", name, action_string);
- send_message(friend_number, "Currently supported commands: j, join, h, help, invite");
- }
- private void on_groupchat_message(Tox.Tox tox, int groupnumber, int friendgroupnumber, uint8[] message) {
- uint8[] name_buf = new uint8[Tox.MAX_NAME_LENGTH];
- if( tox.group_peername(groupnumber, friendgroupnumber, name_buf) < 0 ) {
- stderr.printf("[ERR] Could not get name for peer #%i\n", friendgroupnumber);
+ private static string get_peer_name(Tox tox, uint32 conference_number, uint32 peer_number) {
+ var err = ErrConferencePeerQuery.OK;
+ var name = tox.conference_peer_get_name(conference_number, peer_number, out err);
+ if (err != ErrConferencePeerQuery.OK) {
+ stderr.printf("[ERR] Could not get name for peer #%u: %s\n", peer_number, err.to_string());
+ return "PEER #%u".printf(peer_number);
}
- string friend_name = (string)name_buf;
- stdout.printf("[GM ] %s: %s\n", friend_name, (string)message);
+ return name;
}
- private void on_group_namelist_change(Tox.Tox tox, int groupnumber, int peernumber, Tox.ChatChange change) {
- if(change == Tox.ChatChange.PEER_ADD || change == Tox.ChatChange.PEER_DEL) {
- stdout.printf("[LOG] Peer connected/disconnect, updating status message\n");
- update_status_message();
- }
+ private static void on_conference_message(Tox tox, uint32 conference_number, uint32 peer_number, MessageType type, uint8[] message, void* data) {
+ var name = get_peer_name(tox, conference_number, peer_number);
+ stdout.printf("[CM ] %s: %s\n", name, (string) message);
}
- private void on_friend_request(uint8[] key, uint8[] data) {
- uint8[] public_key = Venom.Tools.clone(key, Tox.CLIENT_ID_SIZE);
- stdout.printf("[LOG] Friend request from %s received.\n", Venom.Tools.bin_to_hexstring(public_key));
- int friend_number = tox.add_friend_norequest(public_key);
- if(friend_number < 0) {
- stderr.printf("[ERR] Friend could not be added.\n");
+ private static void on_friend_request(Tox tox, uint8[] key, uint8[] message, void* data) {
+ var pub_key = copy_data(key, address_size());
+ stdout.printf("[LOG] Friend request from %s received.\n", Venom.Tools.bin_to_hexstring(pub_key));
+ var err = ErrFriendAdd.OK;
+ tox.friend_add_norequest(pub_key, out err);
+ if (err != ErrFriendAdd.OK) {
+ stderr.printf("[ERR] Could not add friend: %s\n", err.to_string());
}
}
-
- private bool send_message(int friend_number, string message) {
- return tox.send_message(friend_number,
- Venom.Tools.string_to_nullterm_uint(message)) != 0;
+
+ private static void on_friend_connection_status(Tox tox, uint32 friend_number, Connection connection_status, void* data) {
+ var name = get_friend_name(tox, friend_number);
+ stdout.printf("[LOG] Connection status changed for friend #%u (%s): %s\n", friend_number, name, connection_status.to_string());
+ if (connection_status == Connection.NONE) {
+ return;
+ }
+ var err = ErrFriendSendMessage.OK;
+ tox.friend_send_message(friend_number, MessageType.NORMAL, "info", out err);
+ if (err != ErrFriendSendMessage.OK) {
+ stderr.printf("[ERR] Could not send message to %u: %s\n", friend_number, err.to_string());
+ return;
+ }
+ tox.friend_send_message(friend_number, MessageType.NORMAL, "invite", out err);
+ if (err != ErrFriendSendMessage.OK) {
+ stderr.printf("[ERR] Could not send message to %u: %s\n", friend_number, err.to_string());
+ return;
+ }
}
- private void on_friend_message(Tox.Tox tox, int friend_number, uint8[] message) {
- string name = get_name(friend_number);
- string message_str = (string) message;
- stdout.printf("[PM ] %s: %s\n", name, message_str);
-
- GLib.MatchInfo info = null;
- if(message_str == "invite") {
- int groupchat_number = channels.get(DEFAULT_CHANNEL);
- stdout.printf("[LOG] Inviting '%s' to default groupchat #%i\n", name, groupchat_number);
- if(tox.invite_friend(friend_number, groupchat_number) != 0) {
- stderr.printf("[ERR] Failed to invite '%s' to groupchat #%i\n", name, groupchat_number);
- }
- } else if (Venom.Tools.action_regex.match(message_str, 0, out info)) {
- string action_name = info.fetch_named("action_name");
- string action_string = info.fetch_named("action_string");
- ActionWrapper w = actions.get(action_name);
- if(w != null) {
- w.action(action_string != null ? action_string : "", friend_number);
- } else {
- stderr.printf("[ERR] Action \"%s\" not understood.\n", action_name);
- send_message(friend_number, "Error: action %s not understood.".printf(action_name));
+ private static void on_friend_message(Tox tox, uint32 friend_number, MessageType type, uint8[] message, void* data) {
+ var gb = data as GroupBot;
+ var name = get_friend_name(tox, friend_number);
+ var message_str = copy_data_string(message);
+ stdout.printf("[LOG] Message from %s: %s\n", name, message_str);
+ if (message_str.has_prefix("invite")) {
+ var error = ErrConferenceInvite.OK;
+ tox.conference_invite(friend_number, gb.channels.@get(DEFAULT_CHANNEL), out error);
+ if (error != ErrConferenceInvite.OK) {
+ stderr.printf("[ERR] Could not invite %s to channel %u\n", name, gb.channels.@get(DEFAULT_CHANNEL));
+ return;
}
+ stdout.printf("[LOG] Sent an invite to %s\n", name);
}
}
- private void update_status_message() {
- int group_number_peers = tox.group_number_peers(channels.get(DEFAULT_CHANNEL));
- string status_message = "send me 'invite' to get invited to groupchat (%i online)".printf(group_number_peers);
- if(group_number_peers < 0 || tox.set_status_message(Venom.Tools.string_to_nullterm_uint(status_message)) < 0) {
- stderr.printf("[ERR] Setting status message failed.\n");
- }
+ private static string copy_data_string(uint8[] data) {
+ var t = new uint8[data.length + 1];
+ Memory.copy(t, data, data.length);
+ return (string) t;
+ }
+
+ private static uint8[] copy_data(uint8[] data, uint len) {
+ var t = new uint8[len];
+ Memory.copy(t, data, len);
+ return t;
}
- public void run(string ip_string, string pub_key_string, int port = 33445, bool ipv6 = true) {
- tox.bootstrap_from_address(ip_string,
- ipv6 ? 1 : 0,
- ((uint16)port).to_big_endian(),
- Venom.Tools.hexstring_to_bin(pub_key_string)
- );
+ public void run(string ip_string, string pub_key_string, uint16 port = 33445)
+ requires(pub_key_string != null && ip_string != null && port != 0) {
+ stdout.printf("[LOG] Running Groupbot\n");
+ var pub_key = Venom.Tools.hexstring_to_bin(pub_key_string);
- uint8[] buf = new uint8[Tox.FRIEND_ADDRESS_SIZE];
- tox.get_address(buf);
- stdout.printf("[LOG] Tox ID: %s\n", Venom.Tools.bin_to_hexstring(buf));
+ assert(pub_key.length == public_key_size());
+ stdout.printf("[LOG] Bootstrap node: %s:%u.\n", ip_string, port);
- if(tox.set_name(Venom.Tools.string_to_nullterm_uint("Group bot")) != 0) {
- stderr.printf("[ERR] Setting user name failed.\n");
+ stdout.printf("[LOG] Bootstrapping...\n");
+ var error_bootstrap = ErrBootstrap.OK;
+ if (!tox.bootstrap(ip_string, (uint16) port, pub_key, out error_bootstrap)) {
+ stderr.printf("[ERR] Bootstrapping failed: %s\n", error_bootstrap.to_string());
+ return;
}
- update_status_message();
+ stdout.printf("[LOG] Bootstrapping done.\n");
+ stdout.printf("[LOG] Tox ID: %s\n", Venom.Tools.bin_to_hexstring(tox.self_get_address()));
- bool connection_status = false;
- bool running = true;
- while( running ) {
- bool new_connection_status = (tox.isconnected() != 0);
- if(new_connection_status != connection_status) {
+ var setNameError = ErrSetInfo.OK;
+ if (!tox.self_set_name("Groupbot", out setNameError) || setNameError != ErrSetInfo.OK) {
+ stderr.printf("[ERR] Setting user name failed: %s\n", setNameError.to_string());
+ return;
+ }
+
+ stdout.printf("[LOG] Connecting...\n");
+ while (running) {
+ var new_connection_status = tox.self_get_connection_status();
+ if (new_connection_status != connection_status) {
+ switch (new_connection_status) {
+ case Connection.NONE:
+ stdout.printf("[LOG] Not Connected.\n");
+ break;
+ case Connection.UDP:
+ case Connection.TCP:
+ stdout.printf("[LOG] Connected.\n");
+ var groupbot_pub_key = Venom.Tools.hexstring_to_bin("56A1ADE4B65B86BCD51CC73E2CD4E542179F47959FE3E0E21B4B0ACDADE51855D34D34D37CB5");
+ var addFriendErr = ErrFriendAdd.OK;
+ tox.friend_add(groupbot_pub_key, "Please add me", out addFriendErr);
+ if (addFriendErr != ErrFriendAdd.OK) {
+ stderr.printf("[ERR] Could not add friend: %s\n", addFriendErr.to_string());
+ } else {
+ stdout.printf("[LOG] Friend request sent.\n");
+ }
+ break;
+ }
connection_status = new_connection_status;
- if(connection_status)
- stdout.printf("[LOG] Connected to DHT.\n");
- else
- stdout.printf("[LOG] Connection to DHT lost.\n");
}
- tox.do();
- Thread.usleep(25000);
+ tox.iterate(this);
+ MainContext.@default().iteration(false);
+ Thread.usleep(tox.iteration_interval() * 1000);
}
+ stdout.printf("[LOG] Saved tox data, exiting now.\n");
+ }
+
+ private static bool on_sig_int() {
+ running = false;
+ return false;
}
public static void main(string[] args) {
- GroupBot bot = new GroupBot();
- bot.run("66.175.223.88", "B24E2FB924AE66D023FE1E42A2EE3B432010206F751A2FFD3E297383ACF1572E");
+ Unix.signal_add(Posix.Signal.INT, on_sig_int, Priority.HIGH);
+ var bot = new GroupBot();
+ bot.run("node.tox.biribiri.org", "F404ABAA1C99A9D37D61AB54898F56793E1DEF8BD46B1038B9D822E8460FAB67");
}
}
}
diff --git a/src/testing/TestAbout.vala b/src/testing/TestAbout.vala
new file mode 100644
index 0000000..35c4203
--- /dev/null
+++ b/src/testing/TestAbout.vala
@@ -0,0 +1,77 @@
+/*
+ * TestAbout.vala
+ *
+ * Copyright (C) 2017-2018 Venom authors and contributors
+ *
+ * This file is part of Venom.
+ *
+ * Venom is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Venom is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Venom. If not, see .
+ */
+
+using Venom;
+using Mock;
+using Testing;
+
+public class TestAbout : UnitTest {
+ private ILogger logger;
+
+ public TestAbout() {
+ add_func("/test_gtk", test_gtk);
+ add_func("/test_about", test_about);
+ add_func("/test_about_text", test_about_text);
+ }
+
+ public override void set_up() throws Error {
+ logger = new MockLogger();
+ }
+
+ private void test_gtk() throws Error {
+ var widget = new Gtk.Button();
+ Assert.assert_true(widget is Gtk.Button);
+ }
+
+ private void test_about() throws Error {
+ var widget = new Venom.AboutDialog(logger);
+ Assert.assert_true(widget is Gtk.AboutDialog);
+ }
+
+ private void test_about_text() throws Error {
+ var widget = new Venom.AboutDialog(logger);
+ Assert.assert_not_null(widget.authors);
+ Assert.assert_not_null(widget.artists);
+ Assert.assert_not_null(widget.translator_credits);
+ Assert.assert_equals(widget.license_type, Gtk.License.GPL_3_0);
+ Assert.assert_null(widget.logo);
+ }
+
+ private static int main(string[] args) {
+ Test.init(ref args);
+
+ if (!Test.slow()) {
+ return 77;
+ }
+
+ Gtk.init(ref args);
+
+ Idle.add(() => {
+ var test = new TestAbout();
+ Test.run();
+ Gtk.main_quit();
+ return false;
+ });
+
+ Gtk.main();
+ return 0;
+ }
+}
diff --git a/src/testing/TestContact.vala b/src/testing/TestContact.vala
new file mode 100644
index 0000000..07b7ddf
--- /dev/null
+++ b/src/testing/TestContact.vala
@@ -0,0 +1,57 @@
+/*
+ * TestContact.vala
+ *
+ * Copyright (C) 2017-2018 Venom authors and contributors
+ *
+ * This file is part of Venom.
+ *
+ * Venom is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Venom is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Venom. If not, see .
+ */
+
+using Venom;
+using Mock;
+using Testing;
+
+public class TestContact : UnitTest {
+ public TestContact() {
+ add_func("/test_contact", test_contact);
+ add_func("/test_contact_name", test_contact_name);
+ }
+
+ private static void test_contact() throws Error {
+ var public_key = new uint8[ToxCore.public_key_size()];
+ var contact = new Contact(1, "id");
+ Assert.assert_true(contact.tox_friend_number == 1);
+
+ Assert.assert_true(contact.get_id() == "id");
+ Assert.assert_true(contact.get_name_string() == "id");
+ Assert.assert_true(contact.get_status_string() == "");
+ Assert.assert_true(contact.get_status() == UserStatus.NONE);
+ Assert.assert_true(contact.is_connected() == false);
+ }
+
+ private static void test_contact_name() throws Error {
+ var contact = new Contact(0, "");
+ contact.name = "name";
+ Assert.assert_true(contact.name == "name");
+ Assert.assert_true(contact.get_name_string() == "name");
+ }
+
+ private static int main(string[] args) {
+ Test.init(ref args);
+ var test = new TestContact();
+ Test.run();
+ return 0;
+ }
+}
diff --git a/src/testing/TestDht.vala b/src/testing/TestDht.vala
deleted file mode 100644
index 4c89ca4..0000000
--- a/src/testing/TestDht.vala
+++ /dev/null
@@ -1,70 +0,0 @@
-/*
- * ToxTestDht.vala
- *
- * Copyright (C) 2013-2014 Venom authors and contributors
- *
- * This file is part of Venom.
- *
- * Venom is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * Venom is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with Venom. If not, see .
- */
-
-namespace Testing {
- public class TestDht : GLib.Object {
- public void run_connection_test(string ip_string, string pub_key_string, int port = 33445, int timeout = 100, bool ipv6 = false) {
- Tox.Tox tox = new Tox.Tox(ipv6 ? 1 : 0);
- string ip_address = ip_string;
- uint16 ip_port_be = ((uint16)port).to_big_endian();
- uint8[] pub_key = Venom.Tools.hexstring_to_bin(pub_key_string);
-
- stdout.printf("Connecting to: %s:%u\n", ip_address, port);
- stdout.printf("Public key: %s\n", pub_key_string);
-
- tox.bootstrap_from_address(ip_address, ipv6 ? 1 : 0, ip_port_be, pub_key);
-
- bool connected = false;
- for(int i = 0; i < timeout; ++i) {
- if(connected = (tox.isconnected() != 0))
- break;
- tox.do();
- Thread.usleep(25000);
- }
- if(connected) {
- stdout.printf("[x] Connection successfully established.\n");
- } else {
- stdout.printf("[ ] Could not establish connection!\n");
- }
- stdout.printf("----------------------------------------\n");
- stdout.flush();
- }
-
- public static void main(string[] args) {
- TestDht test = new TestDht();
- test.run_connection_test("192.81.133.111", "8CD5A9BF0A6CE358BA36F7A653F99FA6B258FF756E490F52C1F98CC420F78858");
- test.run_connection_test("66.175.223.88", "B24E2FB924AE66D023FE1E42A2EE3B432010206F751A2FFD3E297383ACF1572E");
- test.run_connection_test("192.184.81.118", "5CD7EB176C19A2FD840406CD56177BB8E75587BB366F7BB3004B19E3EDC04143");
- test.run_connection_test("192.210.149.121","F404ABAA1C99A9D37D61AB54898F56793E1DEF8BD46B1038B9D822E8460FAB67");
- test.run_connection_test("81.224.34.47", "48F0D94C0D54EB1995A2ECEDE7DB6BDD5E05D81704B2F3D1BB9FE43AC97B7269", 443);
- test.run_connection_test("198.46.136.167", "728925473812C7AAC482BE7250BCCAD0B8CB9F737BF3D42ABD34459C1768F854");
- test.run_connection_test("95.47.140.214", "F4BF7C5A9D0EF4CB684090C38DE937FAE1612021F21FEA4DCBFAC6AAFEF58E68");
- test.run_connection_test("54.215.145.71", "6EDDEE2188EF579303C0766B4796DCBA89C93058B6032FEA51593DCD42FB746C");
- test.run_connection_test("66.74.30.125", "7155386A691E7BD3C4C0589D70ACDA191D488634772885CCED5DD7B3F7E6310D");
- test.run_connection_test("69.42.220.58", "9430A83211A7AD1C294711D069D587028CA0B4782FA43CB9B30008247A43C944");
- test.run_connection_test("31.192.105.19", "D59F99384592DE4C8AB9D534D5197DB90F4755CC9E975ED0C565E18468A1445B");
- test.run_connection_test("5.39.218.35", "CC2B02636A2ADBC2871D6EC57C5E9589D4FD5E6F98A14743A4B949914CF26D39");
- stdout.printf("Testing done, press any key to close.\n");
- char c;
- stdin.scanf("%c", out c);
- }
- }
-}
diff --git a/src/testing/TestDhtNodeDb.vala b/src/testing/TestDhtNodeDb.vala
new file mode 100644
index 0000000..776084b
--- /dev/null
+++ b/src/testing/TestDhtNodeDb.vala
@@ -0,0 +1,142 @@
+/*
+ * TestDhtNodeDb.vala
+ *
+ * Copyright (C) 2017-2018 Venom authors and contributors
+ *
+ * This file is part of Venom.
+ *
+ * Venom is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Venom is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Venom. If not, see .
+ */
+
+using Venom;
+using Mock;
+using Testing;
+
+public class TestDhtNodeDb : UnitTest {
+ private ILogger logger;
+ private IDatabaseStatementFactory statement_factory;
+ private IDatabaseStatement statement;
+ private IDhtNodeFactory node_factory;
+ private IDatabaseStatementBuilder builder;
+
+ public TestDhtNodeDb() {
+ add_func("test_init", test_init);
+ add_func("test_real_dht_node_db", test_real_dht_node_db);
+ add_func("test_insert", test_insert);
+ add_func("test_select", test_select);
+ add_func("test_real_dht_node_db_insert_select", test_real_dht_node_db_insert_select);
+ add_func("test_real_dht_node_db_insert_select_duplicate", test_real_dht_node_db_insert_select_duplicate);
+ add_func("test_real_dht_node_db_delete", test_real_dht_node_db_delete);
+ add_func("test_real_dht_node_db_insert_delete_select", test_real_dht_node_db_insert_delete_select);
+ }
+
+ public override void set_up() throws GLib.Error {
+ logger = new MockLogger();
+ statement = new MockStatement();
+ builder = new SqliteStatementWrapper.Builder(statement);
+ statement_factory = new MockStatementFactory();
+ node_factory = new MockDhtNodeFactory();
+
+ mock().when(statement, "builder").then_return_object(builder);
+ mock().when(statement_factory, "createStatement", args().string("", any_string()).create())
+ .then_return_object(statement);
+ }
+
+ private void test_init() throws GLib.Error {
+ var database = new SqliteDhtNodeDatabase(statement_factory, logger);
+ Assert.assert_not_null(database);
+ }
+
+ private void test_real_dht_node_db() throws GLib.Error {
+ var factory = new SqliteWrapperFactory();
+ var db = factory.createDatabase(":memory:");
+ var statement_factory = factory.createStatementFactory(db);
+ var node_database = new SqliteDhtNodeDatabase(statement_factory, logger);
+ Assert.assert_not_null(node_database);
+ }
+
+ private void test_insert() throws GLib.Error {
+ var node_database = new SqliteDhtNodeDatabase(statement_factory, logger);
+ Assert.assert_not_null(node_database);
+ node_database.insertDhtNode("a", "b", 0, false, "c", "d");
+
+ mock().verify(statement, "bind_text", args().string("$KEY").string("a").create());
+ mock().verify(statement, "bind_text", args().string("$ADDRESS").string("b").create());
+ mock().verify(statement, "bind_text", args().string("$OWNER").string("c").create());
+ mock().verify(statement, "bind_text", args().string("$LOCATION").string("d").create());
+ mock().verify(statement, "bind_int", args().string("$PORT").int(0).create());
+ mock().verify(statement, "bind_bool", args().string("$ISBLOCKED").bool(false).create());
+ mock().verify_count(statement, "step", 2);
+ }
+
+ private void test_select() throws GLib.Error {
+ var node_database = new SqliteDhtNodeDatabase(statement_factory, logger);
+ Assert.assert_not_null(node_database);
+
+ var nodes = node_database.getDhtNodes(node_factory);
+ Assert.assert_equals(0, nodes.length());
+ }
+
+ private void test_real_dht_node_db_insert_select() throws GLib.Error {
+ var statement_factory = create_memory_stmt_factory();
+ var node_database = new SqliteDhtNodeDatabase(statement_factory, logger);
+ Assert.assert_not_null(node_database);
+
+ node_database.insertDhtNode("a", "b", 0, false, "c", "d");
+ var nodes = node_database.getDhtNodes(node_factory);
+ Assert.assert_equals(1, nodes.length());
+ }
+
+ private void test_real_dht_node_db_insert_select_duplicate() throws GLib.Error {
+ var statement_factory = create_memory_stmt_factory();
+ var node_database = new SqliteDhtNodeDatabase(statement_factory, logger);
+ Assert.assert_not_null(node_database);
+
+ node_database.insertDhtNode("a", "b", 0, false, "c", "d");
+ node_database.insertDhtNode("a", "e", 0, false, "f", "g");
+ var nodes = node_database.getDhtNodes(node_factory);
+ Assert.assert_equals(1, nodes.length());
+ }
+
+ private void test_real_dht_node_db_delete() throws GLib.Error {
+ var statement_factory = create_memory_stmt_factory();
+ var node_database = new SqliteDhtNodeDatabase(statement_factory, logger);
+ Assert.assert_not_null(node_database);
+
+ node_database.deleteDhtNode("a");
+ }
+
+ private void test_real_dht_node_db_insert_delete_select() throws GLib.Error {
+ var statement_factory = create_memory_stmt_factory();
+ var node_database = new SqliteDhtNodeDatabase(statement_factory, logger);
+ Assert.assert_not_null(node_database);
+
+ node_database.insertDhtNode("a", "b", 0, false, "c", "d");
+ node_database.deleteDhtNode("a");
+ var nodes = node_database.getDhtNodes(node_factory);
+ Assert.assert_equals(0, nodes.length());
+ }
+
+ private IDatabaseStatementFactory create_memory_stmt_factory() {
+ var factory = new SqliteWrapperFactory();
+ var db = factory.createDatabase(":memory:");
+ return factory.createStatementFactory(db);
+ }
+
+ private static void main(string[] args) {
+ Test.init(ref args);
+ var test = new TestDhtNodeDb();
+ Test.run();
+ }
+}
diff --git a/src/core/User.vala b/src/testing/TestGlibTesting.vala
similarity index 59%
rename from src/core/User.vala
rename to src/testing/TestGlibTesting.vala
index 1d24f66..1a82f00 100644
--- a/src/core/User.vala
+++ b/src/testing/TestGlibTesting.vala
@@ -1,7 +1,7 @@
/*
- * User.vala
+ * TestGlibTesting.vala
*
- * Copyright (C) 2013-2014 Venom authors and contributors
+ * Copyright (C) 2017 Venom authors and contributors
*
* This file is part of Venom.
*
@@ -19,24 +19,15 @@
* along with Venom. If not, see .
*/
-namespace Venom {
- public class User : GLib.Object{
- private static User? _instance;
- public static User instance {
- get {
- if( _instance == null )
- _instance = new User();
- return _instance;
- }
- private set {
- _instance = value;
- }
- }
+namespace TestGlibTesting {
- public string name { get; set; }
- public string status_message { get; set; }
+ private static void test_glib_testing() {
+ stdout.printf("Unit test frameworks appears to be ok.\n");
+ }
- private User() {
- }
+ private static void main(string[] args) {
+ Test.init(ref args);
+ Test.add_func("/test_glib_testing", test_glib_testing);
+ Test.run();
}
}
diff --git a/src/testing/TestJsonWebDhtNodeDb.vala b/src/testing/TestJsonWebDhtNodeDb.vala
new file mode 100644
index 0000000..028b312
--- /dev/null
+++ b/src/testing/TestJsonWebDhtNodeDb.vala
@@ -0,0 +1,60 @@
+/*
+ * TestJsonWebDhtNodeDb.vala
+ *
+ * Copyright (C) 2017 Venom authors and contributors
+ *
+ * This file is part of Venom.
+ *
+ * Venom is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Venom is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Venom. If not, see .
+ */
+
+using Venom;
+using Mock;
+
+namespace TestJsonWebDhtNodeDb {
+ private static ILogger logger;
+ private static IDhtNodeFactory nodeFactory;
+
+ private static void before() {
+ logger = new MockLogger();
+ nodeFactory = new MockDhtNodeFactory();
+ }
+
+ private static void testWebNodeDb() {
+ before();
+ var database = new JsonWebDhtNodeDatabase(logger);
+ assert_nonnull(database);
+ }
+
+ private static void testWebNodeDbGet() {
+ before();
+ var database = new JsonWebDhtNodeDatabase(logger);
+ assert_nonnull(database);
+ var nodes = database.getDhtNodes(nodeFactory);
+ assert(nodes.length() != 0);
+ }
+
+ private static int main(string[] args) {
+ Test.init(ref args);
+
+ if (!Test.slow()) {
+ return 77;
+ }
+
+ Test.add_func("/test_web_node_db", testWebNodeDb);
+ Test.add_func("/test_web_node_db_get", testWebNodeDbGet);
+ Test.run();
+ return 0;
+ }
+}
diff --git a/src/testing/TestMessageDb.vala b/src/testing/TestMessageDb.vala
new file mode 100644
index 0000000..ec45086
--- /dev/null
+++ b/src/testing/TestMessageDb.vala
@@ -0,0 +1,88 @@
+/*
+ * TestMessageDb.vala
+ *
+ * Copyright (C) 2017-2018 Venom authors and contributors
+ *
+ * This file is part of Venom.
+ *
+ * Venom is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Venom is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Venom. If not, see .
+ */
+
+using Venom;
+using Mock;
+using Testing;
+
+public class TestMessageDb : UnitTest {
+ private IDatabaseStatementBuilder builder;
+ private IDatabaseStatement statement;
+ private ILoggedMessageFactory messageFactory;
+ private IDatabaseStatementFactory statementFactory;
+ private ILogger logger;
+ private ILoggedMessage message;
+
+ public TestMessageDb() {
+ add_func("test_init", test_init);
+ add_func("test_insert", test_insert);
+ add_func("test_retrieve", test_retrieve);
+ }
+
+ public override void set_up() throws Error {
+ statement = new MockStatement();
+ builder = new SqliteStatementWrapper.Builder(statement);
+ when(statement, "builder")
+ .then_return_object(builder);
+
+ statementFactory = new MockStatementFactory();
+ when(statementFactory, "createStatement", args().string("", any_string()).create())
+ .then_return_object(statement);
+
+ message = new MockLoggedMessage();
+ messageFactory = new MockLoggedMessageFactory();
+ when(messageFactory, "createLoggedMessage")
+ .then_return_object(message);
+
+ logger = new MockLogger();
+ }
+
+ private void test_init() throws Error {
+ var messageDatabase = new SqliteMessageDatabase(statementFactory, logger);
+ Assert.assert_not_null(messageDatabase);
+ }
+
+ private void test_insert() throws Error {
+ var messageDatabase = new SqliteMessageDatabase(statementFactory, logger);
+ Assert.assert_not_null(messageDatabase);
+ var time = new DateTime.now_local();
+ messageDatabase.insertMessage("a", "b", "c", time, true);
+
+ mock().verify(statement, "bind_text", args().string("$USER").string("a").create());
+ mock().verify(statement, "bind_text", args().string("$CONTACT").string("b").create());
+ mock().verify(statement, "bind_text", args().string("$MESSAGE").string("c").create());
+ mock().verify(statement, "bind_int64", args().string("$TIME").int64(time.to_unix()).create());
+ mock().verify(statement, "bind_bool", args().string("$SENDER").bool(true).create());
+ }
+
+ private void test_retrieve() throws Error {
+ var messageDatabase = new SqliteMessageDatabase(statementFactory, logger);
+ Assert.assert_not_null(messageDatabase);
+ var messages = messageDatabase.retrieveMessages("", "", messageFactory);
+ Assert.assert_null(messages);
+ }
+
+ private static void main(string[] args) {
+ Test.init(ref args);
+ var test = new TestMessageDb();
+ Test.run();
+ }
+}
diff --git a/src/testing/TestMock.vala b/src/testing/TestMock.vala
new file mode 100644
index 0000000..569414e
--- /dev/null
+++ b/src/testing/TestMock.vala
@@ -0,0 +1,94 @@
+/*
+ * TestMock.vala
+ *
+ * Copyright (C) 2018 Venom authors and contributors
+ *
+ * This file is part of Venom.
+ *
+ * Venom is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Venom is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Venom. If not, see .
+ */
+
+using Mock;
+
+namespace TestMock {
+
+ private static void test_mock() {
+ var o = new GLib.Object();
+ mock().actual_call(o, "a");
+ mock().verify(o, "a");
+ mock().clear();
+ }
+
+ private static void test_mock_empty() {
+ // check_expectations_noerror();
+ }
+
+ private static void test_mock_fail() {
+ var o = new GLib.Object();
+ try {
+ mock().verify(o, "");
+ mock().clear();
+ } catch (Error e) {
+ return;
+ }
+ Test.fail();
+ }
+
+ private static void test_mock_calls() {
+ var o = new GLib.Object();
+ mock().actual_call(o, "b");
+ mock().verify_count(o, "b", 1);
+ mock().clear();
+ }
+
+ private static void test_mock_calls_multi() {
+ var o = new GLib.Object();
+ mock().actual_call(o, "c");
+ mock().actual_call(o, "c");
+ mock().verify_count(o, "c", 2);
+ mock().clear();
+ }
+
+ private static void test_mock_calls_int_arg() {
+ var o = new GLib.Object();
+ mock().actual_call(o, "c", args().int(1).create());
+ mock().verify(o, "c", args().int(1).create());
+ mock().clear();
+ }
+
+ private static void test_mock_calls_int_arg_fail() {
+ var o = new GLib.Object();
+ try {
+ mock().actual_call(o, "c", args().int(1).create());
+ mock().verify(o, "c", args().int(2).create());
+ } catch {
+ mock().clear();
+ return;
+ }
+ Test.fail();
+ }
+
+ private static void main(string[] args) {
+ Test.init(ref args);
+
+ Test.add_func("/test_mock", test_mock);
+ Test.add_func("/test_mock_empty", test_mock_empty);
+ Test.add_func("/test_mock_fail", test_mock_fail);
+ Test.add_func("/test_mock_calls", test_mock_calls);
+ Test.add_func("/test_mock_calls_multi", test_mock_calls_multi);
+ Test.add_func("/test_mock_calls_int_arg", test_mock_calls_int_arg);
+ Test.add_func("/test_mock_calls_int_arg_fail", test_mock_calls_int_arg_fail);
+ Test.run();
+ }
+}
diff --git a/src/testing/TestObservableList.vala b/src/testing/TestObservableList.vala
new file mode 100644
index 0000000..26555d8
--- /dev/null
+++ b/src/testing/TestObservableList.vala
@@ -0,0 +1,127 @@
+/*
+ * TestObservableList.vala
+ *
+ * Copyright (C) 2018 Venom authors and contributors
+ *
+ * This file is part of Venom.
+ *
+ * Venom is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Venom is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Venom. If not, see .
+ */
+
+namespace TestGenerics {
+ private class SimpleObject : GLib.Object {
+ public static int count = 0;
+
+ public SimpleObject() {
+ stdout.printf("SimpleObject\n");
+ count++;
+ }
+
+ ~SimpleObject() {
+ stdout.printf("~SimpleObject\n");
+ count--;
+ }
+ }
+
+ private class Container : GLib.Object {
+ private GLib.List list;
+ construct {
+ list = new GLib.List();
+ }
+
+ public void add(SimpleObject item) {
+ list.append(item);
+ }
+ }
+
+ private class GenericContainer : GLib.Object {
+ private Gee.List list;
+ construct {
+ list = new Gee.ArrayList();
+ }
+
+ public void add(G item) {
+ if (typeof(G).is_object()) {
+ var o = ((GLib.Object)item);
+ o.ref();
+ o.ref();
+ }
+ list.add(item);
+ }
+
+ public void add_list(GLib.List list) {
+ foreach (var item in list) {
+ this.list.add(item);
+ if (typeof(G).is_object()) {
+ var o = ((GLib.Object)item);
+ o.ref();
+ o.ref();
+ }
+ }
+ }
+
+ ~GenericContainer() {
+ // Vala generics bug
+ if (typeof(G).is_object()) {
+ foreach (var o in list) {
+ ((GLib.Object)o).unref();
+ }
+ }
+ }
+ }
+
+ private static void test_container() {
+ assert(SimpleObject.count == 0);
+ {
+ var list = new Container();
+ list.add(new SimpleObject());
+ assert(SimpleObject.count == 1);
+ }
+ assert(SimpleObject.count == 0);
+ }
+
+ private static void test_generic_container() {
+ assert(SimpleObject.count == 0);
+ {
+ var list = new GenericContainer();
+ list.add(new SimpleObject());
+ assert(SimpleObject.count == 1);
+ }
+ assert(SimpleObject.count == 0);
+ }
+
+ private static void test_generic_container_list_add() {
+ assert(SimpleObject.count == 0);
+ {
+ var container = new GenericContainer();
+ {
+ var list = new GLib.List();
+ list.append(new SimpleObject());
+ container.add_list(list);
+ assert(SimpleObject.count == 1);
+ }
+ assert(SimpleObject.count == 1);
+ }
+ assert(SimpleObject.count == 0);
+ }
+
+ private static int main(string[] args) {
+ Test.init(ref args);
+ Test.add_func("/test_container", test_container);
+ Test.add_func("/test_generic_container", test_generic_container);
+ Test.add_func("/test_generic_container_list_add", test_generic_container_list_add);
+ Test.run();
+ return 0;
+ }
+}
diff --git a/src/testing/TestPlugin.vala b/src/testing/TestPlugin.vala
new file mode 100644
index 0000000..0f707c0
--- /dev/null
+++ b/src/testing/TestPlugin.vala
@@ -0,0 +1,48 @@
+/*
+ * TestPlugin.vala
+ *
+ * Copyright (C) 2018 Venom authors and contributors
+ *
+ * This file is part of Venom.
+ *
+ * Venom is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Venom is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Venom. If not, see .
+ */
+
+using Mock;
+
+namespace TestPlugin {
+ private static void test_plugin() {
+ var logger = new MockLogger();
+ mock().expect_one_call(logger, "i");
+ try {
+ var test_plugin = new Venom.Pluginregistrar(logger, "/../src/testing/libexample_plugin");
+ test_plugin.load();
+
+ var plugin = test_plugin.new_object();
+ plugin.activate(logger);
+ } catch (Error e) {
+ stdout.printf("Loading plugins failed: %s\n", e.message);
+ Test.fail();
+ }
+ //check_expectations_noerror();
+ }
+
+ private static int main(string[] args) {
+ return 77;
+ Test.init(ref args);
+
+ Test.add_func("/test_plugin", test_plugin);
+ Test.run();
+ }
+}
diff --git a/src/testing/TestSqliteDb.vala b/src/testing/TestSqliteDb.vala
new file mode 100644
index 0000000..842fa7a
--- /dev/null
+++ b/src/testing/TestSqliteDb.vala
@@ -0,0 +1,91 @@
+/*
+ * TestSqliteDb.vala
+ *
+ * Copyright (C) 2017-2018 Venom authors and contributors
+ *
+ * This file is part of Venom.
+ *
+ * Venom is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Venom is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Venom. If not, see .
+ */
+
+using Venom;
+using Mock;
+using Testing;
+
+public class TestSqliteDb : UnitTest {
+ public TestSqliteDb() {
+ add_func("/test_sqlite_factory", test_sqlite_factory);
+ add_func("/test_sqlite_database_wrapper", test_sqlite_database_wrapper);
+ add_func("/test_sqlite_statement_wrapper", test_sqlite_statement_wrapper);
+ add_func("/test_sqlite_fail_real_database", test_sqlite_fail_real_database);
+ add_func("/test_sqlite_fail_real_statement", test_sqlite_fail_real_statement);
+ add_func("/test_sqlite_real_statement", test_sqlite_real_statement);
+ }
+
+ private void test_sqlite_factory() throws Error {
+ var factory = new SqliteWrapperFactory();
+ Assert.assert_not_null(factory);
+ }
+
+ private void test_sqlite_database_wrapper() throws Error {
+ var factory = new SqliteWrapperFactory();
+ var database = factory.createDatabase(":memory:");
+ Assert.assert_not_null(database);
+ }
+
+ private void test_sqlite_statement_wrapper() throws Error {
+ var factory = new SqliteWrapperFactory();
+ var database = factory.createDatabase(":memory:");
+ var stmtFactory = factory.createStatementFactory(database);
+ var statement = stmtFactory.createStatement("");
+ Assert.assert_not_null(statement);
+ }
+
+ private void test_sqlite_fail_real_database() throws Error {
+ var factory = new SqliteWrapperFactory();
+ try {
+ factory.createDatabase("file://invalid_path");
+ } catch (Error e) {
+ return;
+ }
+ Test.fail();
+ }
+
+ private void test_sqlite_fail_real_statement() throws Error {
+ var factory = new SqliteWrapperFactory();
+ try {
+ var database = factory.createDatabase(":memory:");
+ var stmtFactory = factory.createStatementFactory(database);
+ var statement = stmtFactory.createStatement("");
+ statement.step();
+ } catch (Error e) {
+ return;
+ }
+ Test.fail();
+ }
+
+ private void test_sqlite_real_statement() throws Error {
+ var factory = new SqliteWrapperFactory();
+ var database = factory.createDatabase(":memory:");
+ var stmtFactory = factory.createStatementFactory(database);
+ var statement = stmtFactory.createStatement("ANALYZE sqlite_master");
+ statement.step();
+ }
+
+ private static void main(string[] args) {
+ Test.init(ref args);
+ var test = new TestSqliteDb();
+ Test.run();
+ }
+}
diff --git a/src/testing/TestToxAdapterFiletransferListener.vala b/src/testing/TestToxAdapterFiletransferListener.vala
new file mode 100644
index 0000000..adc1fac
--- /dev/null
+++ b/src/testing/TestToxAdapterFiletransferListener.vala
@@ -0,0 +1,126 @@
+/*
+ * TestToxAdapterFiletransferListener.vala
+ *
+ * Copyright (C) 2018 Venom authors and contributors
+ *
+ * This file is part of Venom.
+ *
+ * Venom is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Venom is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Venom. If not, see .
+ */
+
+using Venom;
+using Mock;
+using Testing;
+
+public class TestToxAdapterFiletransferListener : UnitTest {
+ private ObservableList transfers;
+ private ILogger logger;
+ private NotificationListener notification_listener;
+ private ToxSession session;
+ private ToxAdapterFiletransferListenerImpl listener;
+ private FileTransfer transfer;
+ private GLib.HashTable conversations;
+ private IContact contact;
+
+ public TestToxAdapterFiletransferListener() {
+ add_func("test_init", test_init);
+ add_func("test_attach", test_attach);
+ add_func("test_start_transfer", test_start_transfer);
+ add_func("test_remove_transfer", test_remove_transfer);
+ add_func("test_remove_exception", test_remove_exception);
+ }
+
+ public override void set_up() throws Error {
+ transfers = new ObservableList();
+ logger = new MockLogger();
+ notification_listener = new MockNotificationListener();
+ session = new MockToxSession();
+ transfer = new MockFiletransfer();
+ conversations = new GLib.HashTable(null, null);
+ contact = new MockContact();
+
+ listener = new ToxAdapterFiletransferListenerImpl(logger, transfers, conversations, notification_listener);
+ }
+
+ private void test_init() throws Error {
+ Assert.assert_not_null(listener);
+ }
+
+ private void test_attach() throws Error {
+ Assert.assert_not_null(listener);
+ listener.attach_to_session(session);
+
+ mock().verify(session, "set_filetransfer_listener", args().object(listener).create());
+ }
+
+ private void test_start_transfer() throws Error {
+ Assert.assert_not_null(listener);
+
+ mock().when(transfer, "get_friend_number").then_return_int(1);
+ mock().when(transfer, "get_file_number").then_return_int(2);
+
+ listener.attach_to_session(session);
+ listener.start_transfer(transfer);
+
+ mock().verify(transfer, "get_friend_number");
+ mock().verify(transfer, "get_file_number");
+ mock().verify(session, "file_control", args().uint(1).uint(2).int(ToxCore.FileControl.RESUME).create());
+ mock().verify(transfer, "set_state", args().int(FileTransferState.RUNNING).create());
+
+ mock().verify_no_more_interactions(transfer);
+ }
+
+ private void test_remove_transfer() throws Error {
+ session.get_friends().set(1, contact);
+ var conversation = new ObservableList();
+ conversation.append(transfer);
+ conversations.set(contact, conversation);
+
+ when(transfer, "get_state").then_return_int(FileTransferState.CANCEL);
+ when(transfer, "get_friend_number").then_return_int(1);
+
+ transfers.append(transfer);
+
+ listener.attach_to_session(session);
+ listener.remove_transfer(transfer);
+ Assert.assert_true(transfers.length() == 0);
+ }
+
+ private void test_remove_exception() throws Error {
+ session.get_friends().set(2, contact);
+ var conversation = new ObservableList();
+ conversation.append(transfer);
+ conversations.set(contact, conversation);
+ when(transfer, "get_friend_number").then_return_int(2);
+
+ mock().when(session, "file_control", args().uint(2).uint(0).int(ToxCore.FileControl.CANCEL).create())
+ .then_throw(new ToxError.GENERIC("this should be caught"));
+
+ transfers.append(transfer);
+ listener.attach_to_session(session);
+ try {
+ listener.remove_transfer(transfer);
+ } catch (Error e) {
+ Assert.assert_true(transfers.length() == 0);
+ return;
+ }
+ Assert.fail();
+ }
+
+ private static void main(string[] args) {
+ Test.init(ref args);
+ var test = new TestToxAdapterFiletransferListener();
+ test.run();
+ }
+}
diff --git a/src/testing/TestToxCore.vala b/src/testing/TestToxCore.vala
new file mode 100644
index 0000000..b480322
--- /dev/null
+++ b/src/testing/TestToxCore.vala
@@ -0,0 +1,167 @@
+/*
+ * TestToxCore.vala
+ *
+ * Copyright (C) 2017 Venom authors and contributors
+ *
+ * This file is part of Venom.
+ *
+ * Venom is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Venom is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Venom. If not, see .
+ */
+
+using ToxCore;
+
+namespace TestToxCore {
+
+ private static void testToxVersion() {
+ assert(ToxCore.Version.major() == ToxCore.Version.MAJOR);
+ assert(ToxCore.Version.minor() == ToxCore.Version.MINOR);
+ assert(ToxCore.Version.patch() == ToxCore.Version.PATCH);
+ assert(ToxCore.Version.is_compatible(ToxCore.Version.MAJOR, ToxCore.Version.MINOR, ToxCore.Version.PATCH));
+ }
+
+ private static void testToxOptions() {
+ var e = ErrOptionsNew.OK;
+ var options = new Options(out e);
+ var default_options = new Options(out e);
+ default_options.default ();
+ assert(options != null);
+ assert(default_options != null);
+
+ assert(options.ipv6_enabled == default_options.ipv6_enabled);
+ assert(options.udp_enabled == default_options.udp_enabled);
+ assert(options.local_discovery_enabled == default_options.local_discovery_enabled);
+ assert(options.proxy_type == default_options.proxy_type);
+ assert(options.proxy_host == default_options.proxy_host);
+ assert(options.start_port == default_options.start_port);
+ assert(options.end_port == default_options.end_port);
+ assert(options.tcp_port == default_options.tcp_port);
+ }
+
+ private static void testToxCoreSession() {
+ var e = ErrOptionsNew.OK;
+ var options = new Options(out e);
+ var error = ErrNew.OK;
+ var tox = new Tox(null, out error);
+ assert(error == ErrNew.OK);
+ tox = new Tox(options, out error);
+ assert(error == ErrNew.OK);
+ }
+
+ private static void testToxSaveData() {
+ var error = ErrNew.OK;
+ var tox = new Tox(null, out error);
+ var savedata = tox.get_savedata();
+ assert(savedata != null);
+ assert(savedata.length > 0);
+ }
+
+ private static void testToxUserStatus() {
+ var error = ErrNew.OK;
+ var tox = new Tox(null, out error);
+ var self_status = UserStatus.AWAY;
+ tox.self_status = self_status;
+ assert(tox.self_status == self_status);
+ }
+
+ private static void testToxPersistentUserStatus() {
+ var error = ErrNew.OK;
+ var tox = new Tox(null, out error);
+ var self_status = UserStatus.BUSY;
+ tox.self_status = self_status;
+ tox = new Tox(null, out error);
+ assert(tox.self_status != self_status);
+ }
+
+ private static void testToxStatusMessage() {
+ var error = ErrNew.OK;
+ var tox = new Tox(null, out error);
+ var message = "message";
+ var setStatusError = ErrSetInfo.OK;
+ assert(tox.self_set_status_message(message, out setStatusError));
+ assert(tox.self_get_status_message() == message);
+ }
+
+ private static void testToxName() {
+ var error = ErrNew.OK;
+ var tox = new Tox(null, out error);
+ var name = "test";
+ var setNameError = ErrSetInfo.OK;
+ assert(tox.self_set_name(name, out setNameError));
+ assert(tox.self_get_name() == name);
+ }
+
+ private static void testToxConnection() {
+ var error = ErrNew.OK;
+ var tox = new Tox(null, out error);
+ assert(tox.self_get_connection_status() == Connection.NONE);
+ }
+
+ private static void testToxPersistentAddress() {
+ var error = ErrNew.OK;
+ var tox = new Tox(null, out error);
+ var address = tox.self_get_address();
+ assert(equals(tox.self_get_address(), address));
+ tox = new Tox(null, out error);
+ assert(!equals(tox.self_get_address(), address));
+ }
+
+ private static void testToxBootstrapNull() {
+ var error = ErrNew.OK;
+ var tox = new Tox(null, out error);
+ var bootstrapError = ErrBootstrap.OK;
+ string s = null;
+ assert(!tox.bootstrap(s, 0, {}, out bootstrapError));
+ assert(bootstrapError == ErrBootstrap.NULL);
+ }
+
+ private static void testToxBootstrapBadPort() {
+ var error = ErrNew.OK;
+ var tox = new Tox(null, out error);
+ var bootstrapError = ErrBootstrap.OK;
+ var pubkey = new uint8[ToxCore.public_key_size()];
+ assert(!tox.bootstrap("", 0, pubkey, out bootstrapError));
+ assert(bootstrapError == ErrBootstrap.BAD_PORT);
+ }
+
+ private static void testToxBootstrapBadHost() {
+ var error = ErrNew.OK;
+ var tox = new Tox(null, out error);
+ var bootstrapError = ErrBootstrap.OK;
+ var pubkey = new uint8[ToxCore.public_key_size()];
+ assert(!tox.bootstrap("", 1, pubkey, out bootstrapError));
+ assert(bootstrapError == ErrBootstrap.BAD_HOST);
+ }
+
+ private static bool equals(uint8[] a, uint8[] b) {
+ return (a != null && b != null && a.length == b.length && Memory.cmp(a, b, a.length) == 0);
+ }
+
+ private static void main(string[] args) {
+ Test.init(ref args);
+ Test.add_func("/test_tox_version", testToxVersion);
+ Test.add_func("/test_tox_options", testToxOptions);
+ Test.add_func("/test_tox_core_session", testToxCoreSession);
+ Test.add_func("/test_tox_save_data", testToxSaveData);
+ Test.add_func("/test_tox_persistent_user_status", testToxPersistentUserStatus);
+ Test.add_func("/test_tox_user_status", testToxUserStatus);
+ Test.add_func("/test_tox_status_message", testToxStatusMessage);
+ Test.add_func("/test_tox_name", testToxName);
+ Test.add_func("/test_tox_connection", testToxConnection);
+ Test.add_func("/test_tox_persistent_address", testToxPersistentAddress);
+ Test.add_func("/test_tox_bootstrap_null", testToxBootstrapNull);
+ Test.add_func("/test_tox_bootstrap_bad_port", testToxBootstrapBadPort);
+ Test.add_func("/test_tox_bootstrap_bad_host", testToxBootstrapBadHost);
+ Test.run();
+ }
+}
diff --git a/src/testing/TestUndo.vala b/src/testing/TestUndo.vala
new file mode 100644
index 0000000..b526cc9
--- /dev/null
+++ b/src/testing/TestUndo.vala
@@ -0,0 +1,286 @@
+/*
+ * TestUndo.vala
+ *
+ * Copyright (C) 2018 Venom authors and contributors
+ *
+ * This file is part of Venom.
+ *
+ * Venom is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Venom is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Venom. If not, see .
+ */
+
+using Mock;
+using Testing;
+using Undo;
+
+public class MockCommand : UndoCommand, GLib.Object {
+ public void redo() {
+ mock().actual_call(this, "redo");
+ }
+ public void undo() {
+ mock().actual_call(this, "undo");
+ }
+ public bool run_on_init() {
+ return mock().actual_call(this, "run_on_init").get_bool();
+ }
+ public bool try_merge(UndoCommand command) {
+ var args = Arguments.builder()
+ .object(command)
+ .create();
+ return mock().actual_call(this, "try_merge", args).get_bool();
+ }
+}
+
+public class TestUndo : UnitTest {
+ private UndoStack undo_stack;
+ public TestUndo() {
+ add_func("/test_undo_stack_init", test_undo_stack_init);
+ add_func("/test_undo_stack_add_command", test_undo_stack_add_command);
+ add_func("/test_undo_stack_add_command_undo", test_undo_stack_add_command_undo);
+ add_func("/test_undo_stack_add_command_undo_redo", test_undo_stack_add_command_undo_redo);
+ add_func("/test_undo_stack_add_multi_commands", test_undo_stack_add_multi_commands);
+ add_func("/test_undo_stack_add_command_clears_redo", test_undo_stack_add_command_clears_redo);
+ add_func("/test_undo_stack_run_init_false", test_undo_stack_run_init_false);
+ add_func("/test_undo_stack_run_init_true", test_undo_stack_run_init_true);
+ add_func("/test_undo_stack_merge", test_undo_stack_merge);
+ add_func("/test_undo_stack_merge_false", test_undo_stack_merge_false);
+ }
+
+ public override void set_up() throws Error {
+ undo_stack = new SimpleUndoStack();
+ }
+
+ private void test_undo_stack_init() throws Error {
+ Assert.assert_not_null(undo_stack);
+ Assert.assert_false(undo_stack.is_busy);
+
+ var undo_action = undo_stack.create_undo_action("undo");
+ Assert.assert_not_null(undo_action);
+ Assert.assert_equals("undo", undo_action.name);
+ Assert.assert_false(undo_action.enabled);
+
+ var redo_action = undo_stack.create_redo_action("redo");
+ Assert.assert_not_null(redo_action);
+ Assert.assert_equals("redo", redo_action.name);
+ Assert.assert_false(redo_action.enabled);
+ }
+
+ private void test_undo_stack_add_command() throws Error {
+ var command = new MockCommand();
+ var undo_action = undo_stack.create_undo_action("undo");
+ var redo_action = undo_stack.create_redo_action("redo");
+
+ Assert.assert_false(redo_action.enabled);
+ Assert.assert_false(undo_action.enabled);
+
+ undo_stack.offer(command);
+
+ Assert.assert_false(redo_action.enabled);
+ Assert.assert_true(undo_action.enabled);
+
+ undo_stack.clear();
+
+ Assert.assert_false(redo_action.enabled);
+ Assert.assert_false(undo_action.enabled);
+ }
+
+ private void test_undo_stack_add_command_undo() throws Error {
+ var command = new MockCommand();
+ var undo_action = undo_stack.create_undo_action("undo");
+ var redo_action = undo_stack.create_redo_action("redo");
+
+ Assert.assert_false(redo_action.enabled);
+ Assert.assert_false(undo_action.enabled);
+
+ undo_stack.offer(command);
+
+ Assert.assert_false(redo_action.enabled);
+ Assert.assert_true(undo_action.enabled);
+
+ undo_action.activate(null);
+
+ Assert.assert_true(redo_action.enabled);
+ Assert.assert_false(undo_action.enabled);
+
+ undo_stack.clear();
+
+ Assert.assert_false(redo_action.enabled);
+ Assert.assert_false(undo_action.enabled);
+ }
+
+ private void test_undo_stack_add_command_undo_redo() throws Error {
+ var command = new MockCommand();
+ var undo_action = undo_stack.create_undo_action("undo");
+ var redo_action = undo_stack.create_redo_action("redo");
+
+ Assert.assert_false(redo_action.enabled);
+ Assert.assert_false(undo_action.enabled);
+
+ undo_stack.offer(command);
+
+ Assert.assert_false(redo_action.enabled);
+ Assert.assert_true(undo_action.enabled);
+
+ undo_action.activate(null);
+
+ Assert.assert_true(redo_action.enabled);
+ Assert.assert_false(undo_action.enabled);
+
+ redo_action.activate(null);
+
+ Assert.assert_false(redo_action.enabled);
+ Assert.assert_true(undo_action.enabled);
+
+ undo_stack.clear();
+
+ Assert.assert_false(redo_action.enabled);
+ Assert.assert_false(undo_action.enabled);
+ }
+
+ private void test_undo_stack_add_multi_commands() throws Error {
+ var command = new MockCommand();
+ var undo_action = undo_stack.create_undo_action("undo");
+ var redo_action = undo_stack.create_redo_action("redo");
+
+ Assert.assert_false(redo_action.enabled);
+ Assert.assert_false(undo_action.enabled);
+
+ undo_stack.offer(command);
+ undo_stack.offer(command);
+
+ Assert.assert_false(redo_action.enabled);
+ Assert.assert_true(undo_action.enabled);
+
+ undo_action.activate(null);
+
+ Assert.assert_true(redo_action.enabled);
+ Assert.assert_true(undo_action.enabled);
+
+ undo_action.activate(null);
+
+ Assert.assert_true(redo_action.enabled);
+ Assert.assert_false(undo_action.enabled);
+
+ redo_action.activate(null);
+
+ Assert.assert_true(redo_action.enabled);
+ Assert.assert_true(undo_action.enabled);
+
+ redo_action.activate(null);
+
+ Assert.assert_false(redo_action.enabled);
+ Assert.assert_true(undo_action.enabled);
+
+ undo_stack.clear();
+
+ Assert.assert_false(redo_action.enabled);
+ Assert.assert_false(undo_action.enabled);
+ }
+
+ private void test_undo_stack_add_command_clears_redo() throws Error {
+ var command = new MockCommand();
+ var undo_action = undo_stack.create_undo_action("undo");
+ var redo_action = undo_stack.create_redo_action("redo");
+
+ Assert.assert_false(redo_action.enabled);
+ Assert.assert_false(undo_action.enabled);
+
+ undo_stack.offer(command);
+ undo_action.activate(null);
+
+ Assert.assert_true(redo_action.enabled);
+ Assert.assert_false(undo_action.enabled);
+
+ undo_stack.offer(command);
+
+ Assert.assert_false(redo_action.enabled);
+ Assert.assert_true(undo_action.enabled);
+ }
+
+ private void test_undo_stack_run_init_false() throws Error {
+ var command = new MockCommand();
+ undo_stack.offer(command);
+
+ verify(command, "run_on_init");
+ mock().verify_no_more_interactions(command);
+ }
+
+ private void test_undo_stack_run_init_true() throws Error {
+ var command = new MockCommand();
+ when(command, "run_on_init").set_bool(true);
+
+ undo_stack.offer(command);
+
+ verify(command, "redo");
+ verify(command, "run_on_init");
+ mock().verify_no_more_interactions(command);
+ }
+
+ private void test_undo_stack_merge() throws Error {
+ var command = new MockCommand();
+ var command2 = new MockCommand();
+ var undo_action = undo_stack.create_undo_action("undo");
+ var redo_action = undo_stack.create_redo_action("redo");
+
+ when(command, "try_merge", args().object(command2).create())
+ .set_bool(true);
+
+ undo_stack.offer(command);
+ undo_stack.offer(command2);
+
+ Assert.assert_true(undo_action.enabled);
+ Assert.assert_false(redo_action.enabled);
+
+ verify(command, "run_on_init");
+ verify(command, "try_merge", args().object(command2).create());
+ mock().verify_no_more_interactions(command);
+
+ verify(command2, "run_on_init");
+ mock().verify_no_more_interactions(command2);
+
+ undo_action.activate(null);
+ Assert.assert_false(undo_action.enabled);
+ Assert.assert_true(redo_action.enabled);
+ }
+
+ private void test_undo_stack_merge_false() throws Error {
+ var command = new MockCommand();
+ var command2 = new MockCommand();
+ var undo_action = undo_stack.create_undo_action("undo");
+ var redo_action = undo_stack.create_redo_action("redo");
+
+ undo_stack.offer(command);
+ undo_stack.offer(command2);
+
+ Assert.assert_true(undo_action.enabled);
+ Assert.assert_false(redo_action.enabled);
+
+ verify(command, "run_on_init");
+ verify(command, "try_merge", args().object(command2).create());
+ mock().verify_no_more_interactions(command);
+
+ verify(command2, "run_on_init");
+ mock().verify_no_more_interactions(command2);
+
+ undo_action.activate(null);
+ Assert.assert_true(undo_action.enabled);
+ Assert.assert_true(redo_action.enabled);
+ }
+
+ private static void main(string[] args) {
+ Test.init(ref args);
+ var test = new TestUndo();
+ assert(test != null);
+ Test.run();
+ }
+}
diff --git a/src/testing/ToxAVTest.vala b/src/testing/ToxAVTest.vala
new file mode 100644
index 0000000..62fa8e8
--- /dev/null
+++ b/src/testing/ToxAVTest.vala
@@ -0,0 +1,221 @@
+/*
+ * ToxAVTest.vala
+ *
+ * Copyright (C) 2013-2018 Venom authors and contributors
+ *
+ * This file is part of Venom.
+ *
+ * Venom is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Venom is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Venom. If not, see .
+ */
+/*
+ * Using example code from https://wiki.gnome.org/Projects/Vala/GStreamerSample
+ */
+
+using Gtk;
+using Gst;
+
+public class VideoSample : Window {
+
+ private ToxCore.Tox tox;
+ private ToxAV.ToxAV tox_av;
+ private Pipeline pipeline;
+ private Widget video_area;
+ private uint timeout_id;
+
+ construct {
+ destroy.connect(kill);
+
+ setup_gst_pipeline();
+ create_widgets();
+ create_tox();
+
+ pipeline.set_state(State.PLAYING);
+ }
+
+ ~VideoSample() {
+ stdout.printf("[LOG] VideoSample destructed.\n");
+ }
+
+ private void kill() {
+ Source.remove(timeout_id);
+ main_quit();
+ }
+
+ private void create_widgets () {
+ set_default_size(800, 600);
+ var vbox = new Box(Orientation.VERTICAL, 0);
+ vbox.pack_start(video_area);
+
+ var play_button = new Button.from_icon_name("media-playback-start-symbolic", IconSize.BUTTON);
+ var stop_button = new Button.from_icon_name("media-playback-stop-symbolic", IconSize.BUTTON);
+ var quit_button = new Button.from_icon_name("application-exit-symbolic", IconSize.BUTTON);
+
+ play_button.clicked.connect(on_play);
+ stop_button.clicked.connect(on_stop);
+ quit_button.clicked.connect(close);
+
+ var bb = new ButtonBox(Orientation.HORIZONTAL);
+ bb.add(play_button);
+ bb.add(stop_button);
+ bb.add(quit_button);
+ vbox.pack_end(bb, false);
+
+ add(vbox);
+ }
+
+ private void setup_gst_pipeline () {
+ pipeline = new Pipeline("avtestpipeline");
+
+ var src = ElementFactory.make("videotestsrc", null);
+ var sink = ElementFactory.make("gtksink", null);
+ sink.get("widget", out video_area);
+
+ var asrc = ElementFactory.make("audiotestsrc", null);
+ var asink = ElementFactory.make("autoaudiosink", null);
+
+ pipeline.add_many(src, sink, asrc, asink);
+ src.link(sink);
+ asrc.link(asink);
+ }
+
+ private void create_tox() {
+ var err_options = ToxCore.ErrOptionsNew.OK;
+ var options = new ToxCore.Options(out err_options);
+ if (err_options != ToxCore.ErrOptionsNew.OK) {
+ stderr.printf("[FTL] Could not create options: %s\n", err_options.to_string());
+ assert_not_reached();
+ }
+
+ var err = ToxCore.ErrNew.OK;
+ tox = new ToxCore.Tox(options, out err);
+ if (err != ToxCore.ErrNew.OK) {
+ stderr.printf("[FTL] Could not create instance: %s\n", err.to_string());
+ assert_not_reached();
+ }
+
+ tox.callback_friend_request(on_friend_request);
+
+ var err_av = ToxAV.ErrNew.OK;
+ tox_av = new ToxAV.ToxAV(tox, out err_av);
+ if (err_av != ToxAV.ErrNew.OK) {
+ stderr.printf("[FTL] Could not create av instance: %s\n", err_av.to_string());
+ assert_not_reached();
+ }
+
+ tox_av.callback_call(on_call);
+ tox_av.callback_call_state(on_call_state);
+ tox_av.callback_audio_bit_rate(on_audio_bit_rate);
+ tox_av.callback_video_bit_rate(on_video_bit_rate);
+ tox_av.callback_video_receive_frame(on_video_receive_frame);
+ tox_av.callback_audio_receive_frame(on_audio_receive_frame);
+
+ var address = tox.self_get_address();
+ stdout.printf("[LOG] Tox ID: %s\n", Venom.Tools.bin_to_hexstring(address));
+ var err_info = ToxCore.ErrSetInfo.OK;
+ if (!tox.self_set_name("AV Test bot", out err_info)) {
+ stderr.printf("[FTL] Could not set name: %s\n", err_info.to_string());
+ assert_not_reached();
+ }
+
+ var ip_string = "node.tox.biribiri.org";
+ var pub_key_string = "F404ABAA1C99A9D37D61AB54898F56793E1DEF8BD46B1038B9D822E8460FAB67";
+ var port = 33445;
+ var pub_key = Venom.Tools.hexstring_to_bin(pub_key_string);
+
+ var err_bootstrap = ToxCore.ErrBootstrap.OK;
+ if (!tox.bootstrap(ip_string, (uint16) port, pub_key, out err_bootstrap)) {
+ stderr.printf("[ERR] Bootstrapping failed: %s\n", err_bootstrap.to_string());
+ assert_not_reached();
+ }
+ stdout.printf("[LOG] Bootstrapped.\n");
+
+ var connected = false;
+ timeout_id = Timeout.add(tox.iteration_interval(), () => {
+ if (tox.self_get_connection_status() != ToxCore.Connection.NONE) {
+ if (!connected) {
+ connected = true;
+ stdout.printf("[LOG] Connected.\n");
+ }
+ } else {
+ if (connected) {
+ connected = false;
+ stdout.printf("[LOG] Disconnected.\n");
+ }
+ }
+
+ tox.iterate(this);
+ tox_av.iterate();
+ return true;
+ });
+ }
+
+ private string friend_get_name(uint32 friend_number) {
+ var err = ToxCore.ErrFriendQuery.OK;
+ var name = tox.friend_get_name(friend_number, out err);
+ return err != ToxCore.ErrFriendQuery.OK ? "FRIEND #%u".printf(friend_number) : name;
+ }
+
+ private void on_call(ToxAV.ToxAV self, uint32 friend_number, bool audio_enabled, bool video_enabled) {
+ stdout.printf("[LOG] on_call from %s: audio_enabled: %s, video_enabled: %s\n", friend_get_name(friend_number), audio_enabled.to_string(), video_enabled.to_string());
+ }
+
+ private void on_call_state(ToxAV.ToxAV self, uint32 friend_number, ToxAV.FriendCallState state) {
+ stdout.printf("[LOG] on_call_state %s: %i\n", friend_get_name(friend_number), state);
+ }
+
+ private void on_audio_bit_rate(ToxAV.ToxAV self, uint32 friend_number, uint32 audio_bit_rate) {
+ stdout.printf("[LOG] on_audio_bit_rate %s: audio_bit_rate: %u\n", friend_get_name(friend_number), audio_bit_rate);
+ }
+
+ private void on_video_bit_rate(ToxAV.ToxAV self, uint32 friend_number, uint32 video_bit_rate) {
+ stdout.printf("[LOG] on_video_bit_rate %s: video_bit_rate: %u\n", friend_get_name(friend_number), video_bit_rate);
+ }
+
+ private void on_audio_receive_frame(ToxAV.ToxAV self, uint32 friend_number, int16[] pcm, size_t sample_count, uint8 channels, uint32 sampling_rate) {
+ stdout.printf("[LOG] on_audio_receive_frame %s: channels: %u, sampling_rate: %u\n", friend_get_name(friend_number), channels, sampling_rate);
+ }
+
+ private void on_video_receive_frame(ToxAV.ToxAV self, uint32 friend_number, uint16 width, uint16 height, uint8[] y, uint8[] u, uint8[] v, int32 ystride, int32 ustride, int32 vstride) {
+ stdout.printf("[LOG] on_video_receive_frame %s: width: %u, height: %u\n", friend_get_name(friend_number), width, height);
+ }
+
+ private static void on_friend_request(ToxCore.Tox tox, uint8[] key, uint8[] message, void* user_data) {
+ stdout.printf("[LOG] Friend request from %s received: %s\n", Venom.Tools.bin_to_hexstring(key), (string) message);
+ var error = ToxCore.ErrFriendAdd.OK;
+ tox.friend_add_norequest(key, out error);
+ if (error != ToxCore.ErrFriendAdd.OK) {
+ stderr.printf("[ERR] Friend could not be added: %s\n", error.to_string());
+ }
+ }
+
+ private void on_play () {
+ pipeline.set_state(State.PLAYING);
+ }
+
+ private void on_stop () {
+ pipeline.set_state(State.READY);
+ }
+
+ public static int main (string[] args) {
+ Gst.init(ref args);
+ Gtk.init(ref args);
+
+ var sample = new VideoSample();
+ sample.show_all();
+
+ Gtk.main();
+
+ return 0;
+ }
+}
diff --git a/src/testing/meson.build b/src/testing/meson.build
new file mode 100644
index 0000000..e10f982
--- /dev/null
+++ b/src/testing/meson.build
@@ -0,0 +1,158 @@
+root_source_dir = join_paths(meson.current_source_dir(), '..')
+
+if posix_dep.found()
+ executable('group_bot', ['GroupBot.vala',
+ join_paths(root_source_dir, 'core/Tools.vala')],
+ dependencies : [gio_dep, tox_dep, posix_dep]
+ )
+endif
+
+if gst_dep.found()
+ executable('toxav', ['ToxAVTest.vala',
+ join_paths(root_source_dir, 'core/Tools.vala')],
+ dependencies : [gtk_dep, tox_dep, gst_dep]
+ )
+endif
+
+mox_lib = library('mox',
+ [
+ 'util/Assert.vala',
+ 'util/UnitTest.vala',
+ 'util/MockFramework.vala',
+ ],
+ dependencies: [glib_dep, gee_dep]
+ )
+mox_dep = declare_dependency(link_with : mox_lib)
+
+
+test_glib_testing = executable('test_glib_testing', ['TestGlibTesting.vala'],
+ dependencies : [gio_dep]
+ )
+
+test_observable_list = executable('test_observable_list', ['TestObservableList.vala',
+ join_paths(root_source_dir, 'core/ObservableList.vala'),
+ join_paths(root_source_dir, 'core/Interfaces.vala')],
+ dependencies : [gio_dep, gee_dep]
+ )
+
+test_mock = executable('test_mock', ['TestMock.vala'],
+ dependencies : [gio_dep, mox_dep]
+ )
+
+test_tox_core = executable('test_tox_core', ['TestToxCore.vala'],
+ dependencies : [gio_dep, tox_dep]
+ )
+
+test_contact = executable('test_contact', ['TestContact.vala',
+ join_paths(root_source_dir, 'core/Contact.vala'),
+ join_paths(root_source_dir, 'core/Interfaces.vala'),
+ join_paths(root_source_dir, 'core/R.vala'),
+ join_paths(root_source_dir, 'core/Tools.vala'),
+ join_paths(root_source_dir, 'tox/ToxContact.vala')],
+ dependencies : [gtk_dep, config_dep, gdk_dep, tox_dep, mox_dep]
+ )
+
+test_about = executable('test_about', ['TestAbout.vala',
+ 'mocks/MockLogger.vala',
+ join_paths(root_source_dir, 'view/AboutDialog.vala')],
+ join_paths(root_source_dir, 'core/Interfaces.vala'),
+ dependencies : [gtk_dep, config_dep, mox_dep]
+ )
+
+test_sqlite_db = executable('test_sqlite_db', ['TestSqliteDb.vala',
+ join_paths(root_source_dir, 'tox/ContactDatabase.vala'),
+ join_paths(root_source_dir, 'tox/MessageDatabase.vala'),
+ join_paths(root_source_dir, 'core/Interfaces.vala'),
+ join_paths(root_source_dir, 'db/DatabaseInterfaces.vala'),
+ join_paths(root_source_dir, 'db/SqliteWrapper.vala'),
+ join_paths(root_source_dir, 'tox/SqliteDhtNodeDatabase.vala'),
+ join_paths(root_source_dir, 'db/SqliteSettingsDatabase.vala')
+ ],
+ dependencies : [gtk_dep, sqlite_dep, mox_dep]
+ )
+
+test_message_db = executable('test_message_db', ['TestMessageDb.vala',
+ 'mocks/MockLogger.vala',
+ 'mocks/MockDb.vala',
+ 'mocks/MockMessageDb.vala',
+ join_paths(root_source_dir, 'tox/MessageDatabase.vala'),
+ join_paths(root_source_dir, 'tox/SqliteDhtNodeDatabase.vala'),
+ join_paths(root_source_dir, 'db/SqliteSettingsDatabase.vala'),
+ join_paths(root_source_dir, 'db/SqliteWrapper.vala'),
+ join_paths(root_source_dir, 'tox/ContactDatabase.vala'),
+ join_paths(root_source_dir, 'core/Interfaces.vala'),
+ join_paths(root_source_dir, 'db/DatabaseInterfaces.vala')
+ ],
+ dependencies : [gtk_dep, sqlite_dep, mox_dep]
+ )
+
+test_dht_node_db = executable('test_dht_node_db', ['TestDhtNodeDb.vala',
+ 'mocks/MockLogger.vala',
+ 'mocks/MockDb.vala',
+ 'mocks/MockDht.vala',
+ join_paths(root_source_dir, 'tox/DhtNodeDatabase.vala'),
+ join_paths(root_source_dir, 'db/SqliteWrapper.vala'),
+ join_paths(root_source_dir, 'tox/SqliteDhtNodeDatabase.vala'),
+ join_paths(root_source_dir, 'db/SqliteSettingsDatabase.vala'),
+ join_paths(root_source_dir, 'tox/MessageDatabase.vala'),
+ join_paths(root_source_dir, 'tox/ContactDatabase.vala'),
+ join_paths(root_source_dir, 'core/Interfaces.vala'),
+ join_paths(root_source_dir, 'db/DatabaseInterfaces.vala')
+ ],
+ dependencies : [gtk_dep, sqlite_dep, mox_dep]
+ )
+
+test_json_web_dht_node_db = executable('test_json_web_dht_node_db', ['TestJsonWebDhtNodeDb.vala',
+ 'mocks/MockLogger.vala',
+ 'mocks/MockDht.vala',
+ join_paths(root_source_dir, 'tox/JsonWebDhtNodeDatabase.vala'),
+ join_paths(root_source_dir, 'tox/DhtNodeDatabase.vala'),
+ join_paths(root_source_dir, 'core/Interfaces.vala'),
+ join_paths(root_source_dir, 'db/DatabaseInterfaces.vala')
+ ],
+ dependencies : [gtk_dep, soup_dep, json_dep, gee_dep, mox_dep]
+ )
+
+example_plugin_lib = library('example_plugin', ['ExamplePlugin.vala',
+ join_paths(root_source_dir, 'plugin/Plugin.vala'),
+ join_paths(root_source_dir, 'core/Interfaces.vala')
+ ],
+ dependencies : [gio_dep, gmodule_dep]
+ )
+
+test_plugin = executable('test_plugin', ['TestPlugin.vala',
+ 'mocks/MockLogger.vala',
+ join_paths(root_source_dir, 'core/Interfaces.vala'),
+ join_paths(root_source_dir, 'plugin/Pluginregistrar.vala'),
+ join_paths(root_source_dir, 'plugin/Plugin.vala')
+ ],
+ dependencies : [gio_dep, gmodule_dep, mox_dep]
+ )
+
+test_tox_transfer = executable('test_tox_transfer', ['TestToxAdapterFiletransferListener.vala',
+ 'mocks/MockContact.vala',
+ 'mocks/MockLogger.vala',
+ 'mocks/MockFiletransfer.vala',
+ 'mocks/MockNotificationListener.vala',
+ 'mocks/MockToxSession.vala'
+ ],
+ dependencies : [venom_dep, mox_dep]
+ )
+
+test_undo = executable('test_undo', ['TestUndo.vala'],
+ dependencies : [venom_dep, mox_dep]
+ )
+
+test('test glib', test_glib_testing)
+test('test mocking framework', test_mock)
+test('test tox core vapi', test_tox_core)
+test('test tox transfer', test_tox_transfer)
+test('test observable list', test_observable_list)
+test('test contact', test_contact)
+test('test about', test_about)
+test('test sqlite db', test_sqlite_db)
+test('test message db', test_message_db)
+test('test dht node db', test_dht_node_db)
+test('test json web dht node db', test_json_web_dht_node_db)
+test('test plugin', test_plugin)
+test('test undo', test_undo)
diff --git a/src/testing/mocks/MockContact.vala b/src/testing/mocks/MockContact.vala
new file mode 100644
index 0000000..e34662c
--- /dev/null
+++ b/src/testing/mocks/MockContact.vala
@@ -0,0 +1,60 @@
+/*
+ * MockContact.vala
+ *
+ * Copyright (C) 2018 Venom authors and contributors
+ *
+ * This file is part of Venom.
+ *
+ * Venom is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Venom is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Venom. If not, see .
+ */
+
+using Venom;
+using Mock;
+using Testing;
+
+public class MockContact : IContact, GLib.Object {
+ public string get_id() {
+ return mock().actual_call(this, "get_id").get_string();
+ }
+ public string get_name_string() {
+ return mock().actual_call(this, "get_name_string").get_string();
+ }
+ public string get_status_string() {
+ return mock().actual_call(this, "get_status_string").get_string();
+ }
+ public UserStatus get_status() {
+ return (UserStatus) mock().actual_call(this, "get_status").get_int();
+ }
+ public bool is_connected() {
+ return mock().actual_call(this, "is_connected").get_bool();
+ }
+ public bool is_typing() {
+ return mock().actual_call(this, "is_typing").get_bool();
+ }
+ public bool is_conference() {
+ return mock().actual_call(this, "is_connected").get_bool();
+ }
+ public Gdk.Pixbuf get_image() {
+ return (Gdk.Pixbuf) mock().actual_call(this, "get_image").get_object();
+ }
+ public bool get_requires_attention() {
+ return mock().actual_call(this, "get_requires_attention").get_bool();
+ }
+ public void clear_attention() {
+ mock().actual_call(this, "clear_attention");
+ }
+ public bool show_notifications() {
+ return mock().actual_call(this, "show_notifications").get_bool();
+ }
+}
diff --git a/src/testing/mocks/MockDb.vala b/src/testing/mocks/MockDb.vala
new file mode 100644
index 0000000..9cf27a8
--- /dev/null
+++ b/src/testing/mocks/MockDb.vala
@@ -0,0 +1,142 @@
+/*
+ * DatabaseMock.vala
+ *
+ * Copyright (C) 2017-2018 Venom authors and contributors
+ *
+ * This file is part of Venom.
+ *
+ * Venom is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Venom is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Venom. If not, see .
+ */
+
+using Venom;
+
+namespace Mock {
+ public class MockDatabase : IDatabase, Object {}
+
+ public class MockStatement : IDatabaseStatement, Object {
+ public DatabaseResult step() throws DatabaseStatementError {
+ return (DatabaseResult) mock().actual_call(this, "step").get_int();
+ }
+ public void bind_text(string key, string val) throws DatabaseStatementError {
+ var args = Arguments.builder()
+ .string(key)
+ .string(val)
+ .create();
+ mock().actual_call(this, "bind_text", args).get_throws();
+ }
+ public void bind_int64(string key, int64 val) throws DatabaseStatementError {
+ var args = Arguments.builder()
+ .string(key)
+ .int64(val)
+ .create();
+ mock().actual_call(this, "bind_int64", args).get_throws();
+ }
+ public void bind_int(string key, int val) throws DatabaseStatementError {
+ var args = Arguments.builder()
+ .string(key)
+ .int(val)
+ .create();
+ mock().actual_call(this, "bind_int", args).get_throws();
+ }
+ public void bind_bool(string key, bool val) throws DatabaseStatementError {
+ var args = Arguments.builder()
+ .string(key)
+ .bool(val)
+ .create();
+ mock().actual_call(this, "bind_bool", args).get_throws();
+ }
+ public string column_text(int key) throws DatabaseStatementError {
+ var args = Arguments.builder()
+ .int(key)
+ .create();
+ return mock().actual_call(this, "column_text", args).get_string();
+ }
+ public int64 column_int64(int key) throws DatabaseStatementError {
+ var args = Arguments.builder()
+ .int(key)
+ .create();
+ return mock().actual_call(this, "column_int64", args).get_int();
+ }
+ public int column_int(int key) throws DatabaseStatementError {
+ var args = Arguments.builder()
+ .int(key)
+ .create();
+ return mock().actual_call(this, "column_int", args).get_int();
+ }
+ public bool column_bool(int key) throws DatabaseStatementError {
+ var args = Arguments.builder()
+ .int(key)
+ .create();
+ return mock().actual_call(this, "column_bool", args).get_bool();
+ }
+ public void reset() {
+ mock().actual_call(this, "reset");
+ }
+ public IDatabaseStatementBuilder builder() {
+ return (IDatabaseStatementBuilder) mock().actual_call(this, "builder").get_object();
+ }
+ }
+
+ public class MockDatabaseFactory : IDatabaseFactory, Object {
+ public IDatabase createDatabase(string path) throws DatabaseError {
+ var args = Arguments.builder()
+ .string(path)
+ .create();
+ return (IDatabase) mock().actual_call(this, "createDatabase", args).get_object();
+ }
+ public IDatabaseStatementFactory createStatementFactory(IDatabase database) {
+ var args = Arguments.builder()
+ .object(database)
+ .create();
+ return (IDatabaseStatementFactory) mock().actual_call(this, "createStatementFactory", args).get_object();
+ }
+ public IDhtNodeDatabase createNodeDatabase(IDatabaseStatementFactory factory, ILogger logger) throws DatabaseStatementError {
+ var args = Arguments.builder()
+ .object(factory)
+ .object(logger)
+ .create();
+ return (IDhtNodeDatabase) mock().actual_call(this, "createNodeDatabase", args).get_object();
+ }
+ public IContactDatabase createContactDatabase(IDatabaseStatementFactory factory, ILogger logger) throws DatabaseStatementError {
+ var args = Arguments.builder()
+ .object(factory)
+ .object(logger)
+ .create();
+ return (IContactDatabase) mock().actual_call(this, "createContactDatabase", args).get_object();
+ }
+ public IMessageDatabase createMessageDatabase(IDatabaseStatementFactory factory, ILogger logger) throws DatabaseStatementError {
+ var args = Arguments.builder()
+ .object(factory)
+ .object(logger)
+ .create();
+ return (IMessageDatabase) mock().actual_call(this, "createMessageDatabase", args).get_object();
+ }
+ public ISettingsDatabase createSettingsDatabase(IDatabaseStatementFactory factory, ILogger logger) throws DatabaseStatementError {
+ var args = Arguments.builder()
+ .object(factory)
+ .object(logger)
+ .create();
+ return (ISettingsDatabase) mock().actual_call(this, "createSettingsDatabase", args).get_object();
+ }
+ }
+
+ public class MockStatementFactory : IDatabaseStatementFactory, Object {
+ public IDatabaseStatement createStatement(string statement) {
+ var args = Arguments.builder()
+ .string(statement)
+ .create();
+ return (IDatabaseStatement) mock().actual_call(this, "createStatement", args).get_object();
+ }
+ }
+}
diff --git a/src/testing/mocks/MockDht.vala b/src/testing/mocks/MockDht.vala
new file mode 100644
index 0000000..74e734c
--- /dev/null
+++ b/src/testing/mocks/MockDht.vala
@@ -0,0 +1,47 @@
+/*
+ * DhtMock.vala
+ *
+ * Copyright (C) 2017-2018 Venom authors and contributors
+ *
+ * This file is part of Venom.
+ *
+ * Venom is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Venom is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Venom. If not, see .
+ */
+
+using Venom;
+
+namespace Mock {
+ public class MockDhtNode : IDhtNode, Object {
+ public string pub_key { get; set; }
+ public string host { get; set; }
+ public uint port { get; set; }
+ public bool is_blocked { get; set; }
+ public string maintainer { get; set; }
+ public string location { get; set; }
+ }
+
+ public class MockDhtNodeFactory : IDhtNodeFactory, GLib.Object {
+ public IDhtNode createDhtNode(string address, string key, uint port, bool blocked, string owner, string location) {
+ var args = Arguments.builder()
+ .string(address)
+ .string(key)
+ .uint(port)
+ .bool(blocked)
+ .string(owner)
+ .string(location)
+ .create();
+ return (IDhtNode) mock().actual_call(this, "createDhtNode", args).get_object();
+ }
+ }
+}
diff --git a/src/testing/mocks/MockFiletransfer.vala b/src/testing/mocks/MockFiletransfer.vala
new file mode 100644
index 0000000..a0bdcea
--- /dev/null
+++ b/src/testing/mocks/MockFiletransfer.vala
@@ -0,0 +1,77 @@
+/*
+ * MockFiletransfer.vala
+ *
+ * Copyright (C) 2018 Venom authors and contributors
+ *
+ * This file is part of Venom.
+ *
+ * Venom is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Venom is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Venom. If not, see .
+ */
+
+using Venom;
+
+namespace Mock {
+ public class MockFiletransfer : FileTransfer, GLib.Object {
+ public bool is_avatar() {
+ return mock().actual_call(this, "is_avatar").get_bool();
+ }
+ public string get_description() {
+ return mock().actual_call(this, "get_description").get_string();
+ }
+ public uint64 get_transmitted_size() {
+ return mock().actual_call(this, "get_transmitted_size").get_int();
+ }
+ public uint64 get_file_size() {
+ return mock().actual_call(this, "get_file_size").get_int();
+ }
+ public unowned uint8[] ? get_avatar_buffer() {
+ mock().actual_call(this, "get_avatar_buffer");
+ return null;
+ }
+ public void write_data(uint8[] data) throws Error {
+ mock().actual_call(this, "write_data").get_throws();
+ }
+ public uint8[] read_data(uint64 length) throws Error{
+ mock().actual_call(this, "read_data").get_throws();
+ return (uint8[]) null;
+ }
+ public void init_file(File file) throws Error {
+ mock().actual_call(this, "init_file").get_throws();
+ }
+ public FileTransferState get_state() {
+ return (FileTransferState) mock().actual_call(this, "get_state").get_int();
+ }
+ public void set_state(FileTransferState state) {
+ var args = Arguments.builder()
+ .int(state)
+ .create();
+ mock().actual_call(this, "set_state", args);
+ }
+ public string? get_file_name() {
+ return mock().actual_call(this, "get_file_name").get_string();
+ }
+ public string? get_file_path() {
+ return mock().actual_call(this, "get_file_path").get_string();
+ }
+ public uint32 get_friend_number() {
+ return mock().actual_call(this, "get_friend_number").get_int();
+ }
+ public uint32 get_file_number() {
+ return mock().actual_call(this, "get_file_number").get_int();
+ }
+ public FileTransferDirection get_direction() {
+ return (FileTransferDirection) mock().actual_call(this, "get_direction").get_int();
+ }
+ }
+}
diff --git a/src/testing/mocks/MockLogger.vala b/src/testing/mocks/MockLogger.vala
new file mode 100644
index 0000000..1d863f9
--- /dev/null
+++ b/src/testing/mocks/MockLogger.vala
@@ -0,0 +1,34 @@
+/*
+ * MockLogger.vala
+ *
+ * Copyright (C) 2017-2018 Venom authors and contributors
+ *
+ * This file is part of Venom.
+ *
+ * Venom is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Venom is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Venom. If not, see .
+ */
+
+using Venom;
+
+namespace Mock {
+ public class MockLogger : ILogger, Object {
+ public MockLogger() {}
+ public void d(string message) { mock().actual_call(this, "d", args().string(message).create()); }
+ public void i(string message) { mock().actual_call(this, "i", args().string(message).create()); }
+ public void w(string message) { mock().actual_call(this, "w", args().string(message).create()); }
+ public void e(string message) { mock().actual_call(this, "e", args().string(message).create()); }
+ public void f(string message) { mock().actual_call(this, "f", args().string(message).create()); }
+ public void attach_to_glib() { mock().actual_call(this, "attach_to_glib"); }
+ }
+}
diff --git a/src/testing/mocks/MockMessageDb.vala b/src/testing/mocks/MockMessageDb.vala
new file mode 100644
index 0000000..6e60b72
--- /dev/null
+++ b/src/testing/mocks/MockMessageDb.vala
@@ -0,0 +1,39 @@
+/*
+ * MessageDbMock.vala
+ *
+ * Copyright (C) 2017 Venom authors and contributors
+ *
+ * This file is part of Venom.
+ *
+ * Venom is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Venom is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Venom. If not, see .
+ */
+
+using Venom;
+
+namespace Mock {
+ public class MockLoggedMessageFactory : ILoggedMessageFactory, Object {
+ public ILoggedMessage createLoggedMessage(string userId, string contactId, string message, DateTime time, bool outgoing) {
+ var args = Arguments.builder()
+ .string(userId)
+ .string(contactId)
+ .string(message)
+ .bool(outgoing)
+ .create();
+ return (ILoggedMessage) mock().actual_call(this, "createLoggedMessage", args).get_object();
+ }
+ }
+
+ public class MockLoggedMessage : ILoggedMessage, Object {
+ }
+}
diff --git a/src/testing/mocks/MockNotificationListener.vala b/src/testing/mocks/MockNotificationListener.vala
new file mode 100644
index 0000000..0ed20ed
--- /dev/null
+++ b/src/testing/mocks/MockNotificationListener.vala
@@ -0,0 +1,47 @@
+/*
+ * MockNotificationListener.vala
+ *
+ * Copyright (C) 2018 Venom authors and contributors
+ *
+ * This file is part of Venom.
+ *
+ * Venom is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Venom is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Venom. If not, see .
+ */
+
+using Venom;
+
+namespace Mock {
+ public class MockNotificationListener : NotificationListener, GLib.Object {
+ public bool show_notifications { get; set; }
+ public void on_unread_message(IMessage message, IContact c) {
+ var args = Arguments.builder()
+ .object(message)
+ .object(c)
+ .create();
+ mock().actual_call(this, "on_unread_message", args);
+ }
+
+ public void on_filetransfer(FileTransfer transfer, IContact contact) {
+ var args = Arguments.builder()
+ .object(transfer)
+ .object(contact)
+ .create();
+ mock().actual_call(this, "on_filetransfer", args);
+ }
+
+ public void clear_notifications() {
+ mock().actual_call(this, "clear_notifications");
+ }
+ }
+}
diff --git a/src/testing/mocks/MockToxSession.vala b/src/testing/mocks/MockToxSession.vala
new file mode 100644
index 0000000..f46153a
--- /dev/null
+++ b/src/testing/mocks/MockToxSession.vala
@@ -0,0 +1,213 @@
+/*
+ * MockToxSession.vala
+ *
+ * Copyright (C) 2018 Venom authors and contributors
+ *
+ * This file is part of Venom.
+ *
+ * Venom is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Venom is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Venom. If not, see .
+ */
+
+using Venom;
+
+namespace Mock {
+ public class MockToxSession : ToxSession, GLib.Object {
+ private GLib.HashTable contacts;
+ public MockToxSession() {
+ contacts = new GLib.HashTable(null, null);
+ }
+ public void set_session_listener(ToxAdapterSelfListener listener) {
+ var args = Arguments.builder()
+ .object(listener)
+ .create();
+ mock().actual_call(this, "set_session_listener", args);
+ }
+ public void set_filetransfer_listener(ToxAdapterFiletransferListener listener) {
+ var args = Arguments.builder()
+ .object(listener)
+ .create();
+ mock().actual_call(this, "set_filetransfer_listener", args);
+ }
+ public void set_friend_listener(ToxAdapterFriendListener listener) {
+ var args = Arguments.builder()
+ .object(listener)
+ .create();
+ mock().actual_call(this, "set_friend_listener", args);
+ }
+ public void set_conference_listener(ToxAdapterConferenceListener listener) {
+ var args = Arguments.builder()
+ .object(listener)
+ .create();
+ mock().actual_call(this, "set_conference_listener", args);
+ }
+ public void self_set_user_name(string name) {
+ var args = Arguments.builder()
+ .string(name)
+ .create();
+ mock().actual_call(this, "self_set_user_name", args);
+ }
+ public void self_set_user_status(UserStatus status) {
+ var args = Arguments.builder()
+ .int(status)
+ .create();
+ mock().actual_call(this, "self_set_user_status", args);
+ }
+ public UserStatus self_get_user_status() {
+ return (UserStatus) mock().actual_call(this, "self_get_user_status").get_int();
+ }
+ public void self_set_status_message(string status) {
+ var args = Arguments.builder()
+ .string(status)
+ .create();
+ mock().actual_call(this, "self_set_status_message", args);
+ }
+ public void self_set_typing(uint32 friend_number, bool typing) throws ToxError {
+ var args = Arguments.builder()
+ .uint(friend_number)
+ .bool(typing)
+ .create();
+ mock().actual_call(this, "self_set_typing", args).get_throws();
+ }
+ public string self_get_name() {
+ return mock().actual_call(this, "self_get_name").get_string();
+ }
+ public string self_get_status_message() {
+ return mock().actual_call(this, "self_get_status_message").get_string();
+ }
+ public uint8[] self_get_address() {
+ mock().actual_call(this, "self_get_address");
+ return new uint8[0];
+ }
+ public uint8[] self_get_public_key() {
+ mock().actual_call(this, "self_get_public_key");
+ return new uint8[0];
+ }
+ public void self_get_friend_list_foreach(GetFriendListCallback callback) throws ToxError {
+ mock().actual_call(this, "self_get_friend_list_foreach").get_throws();
+ }
+ public void friend_add(uint8[] address, string message) throws ToxError {
+ var args = Arguments.builder()
+ .string(message)
+ .create();
+ mock().actual_call(this, "friend_add", args).get_throws();
+ }
+ public void friend_add_norequest(uint8[] address) throws ToxError {
+ mock().actual_call(this, "friend_add_norequest").get_throws();
+ }
+ public void friend_delete(uint32 friend_number) throws ToxError {
+ var args = Arguments.builder()
+ .uint(friend_number)
+ .create();
+ mock().actual_call(this, "friend_delete", args).get_throws();
+ }
+ public void friend_send_message(uint32 friend_number, string message) throws ToxError {
+ var args = Arguments.builder()
+ .uint(friend_number)
+ .string(message)
+ .create();
+ mock().actual_call(this, "friend_send_message", args).get_throws();
+ }
+ public string friend_get_name(uint32 friend_number) throws ToxError {
+ var args = Arguments.builder()
+ .uint(friend_number)
+ .create();
+ return mock().actual_call(this, "friend_get_name", args).get_string();
+ }
+ public string friend_get_status_message(uint32 friend_number) throws ToxError {
+ var args = Arguments.builder()
+ .uint(friend_number)
+ .create();
+ return mock().actual_call(this, "friend_get_status_message", args).get_string();
+ }
+ public uint64 friend_get_last_online(uint32 friend_number) throws ToxError {
+ var args = Arguments.builder()
+ .uint(friend_number)
+ .create();
+ return mock().actual_call(this, "friend_get_last_online", args).get_int();
+ }
+ public uint32 conference_new(string title) throws ToxError {
+ var args = Arguments.builder()
+ .string(title)
+ .create();
+ return mock().actual_call(this, "conference_new", args).get_int();
+ }
+ public void conference_delete(uint32 conference_number) throws ToxError {
+ var args = Arguments.builder()
+ .uint(conference_number)
+ .create();
+ mock().actual_call(this, "conference_delete", args).get_throws();
+ }
+ public void conference_invite(uint32 friend_number, uint32 conference_number) throws ToxError {
+ var args = Arguments.builder()
+ .uint(friend_number)
+ .uint(conference_number)
+ .create();
+ mock().actual_call(this, "conference_invite", args).get_throws();
+ }
+ public void conference_join(uint32 friend_number, ConferenceType type, uint8[] cookie) throws ToxError {
+ var args = Arguments.builder()
+ .uint(friend_number)
+ .int(type)
+ .create();
+ mock().actual_call(this, "conference_join", args).get_throws();
+ }
+ public void conference_send_message(uint32 conference_number, string message) throws ToxError {
+ var args = Arguments.builder()
+ .uint(conference_number)
+ .string(message)
+ .create();
+ mock().actual_call(this, "conference_send_message", args).get_throws();
+ }
+ public void conference_set_title(uint32 conference_number, string title) throws ToxError {
+ var args = Arguments.builder()
+ .uint(conference_number)
+ .string(title)
+ .create();
+ mock().actual_call(this, "conference_set_title", args).get_throws();
+ }
+ public string conference_get_title(uint32 conference_number) throws ToxError {
+ var args = Arguments.builder()
+ .uint(conference_number)
+ .create();
+ return mock().actual_call(this, "conference_get_title", args).get_string();
+ }
+ public void file_control(uint32 friend_number, uint32 file_number, ToxCore.FileControl control) throws ToxError {
+ var args = Arguments.builder()
+ .uint(friend_number)
+ .uint(file_number)
+ .int(control)
+ .create();
+ mock().actual_call(this, "file_control", args).get_throws();
+ }
+ public void file_send_data(uint32 friend_number, GLib.File file) throws ToxError {
+ var args = Arguments.builder()
+ .uint(friend_number)
+ .create();
+ mock().actual_call(this, "file_send_data", args).get_throws();
+ }
+ public void file_send_avatar(uint32 friend_number, uint8[] avatar_data) throws ToxError {
+ var args = Arguments.builder()
+ .uint(friend_number)
+ .create();
+ mock().actual_call(this, "file_send_avatar", args).get_throws();
+ }
+ public void file_send_chunk(uint32 friend_number, uint32 file_number, uint64 position, uint8[] data) throws ToxError {
+ mock().actual_call(this, "file_send_chunk").get_throws();
+ }
+ public unowned GLib.HashTable get_friends() {
+ mock().actual_call(this, "get_friends");
+ return contacts;
+ }
+ }
+}
diff --git a/src/testing/util/Assert.vala b/src/testing/util/Assert.vala
new file mode 100644
index 0000000..eab1977
--- /dev/null
+++ b/src/testing/util/Assert.vala
@@ -0,0 +1,68 @@
+/*
+ * Assert.vala
+ *
+ * Copyright (C) 2018 Venom authors and contributors
+ *
+ * This file is part of Venom.
+ *
+ * Venom is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Venom is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Venom. If not, see .
+ */
+
+namespace Testing {
+ public errordomain AssertionError {
+ FAILED
+ }
+
+ public class Assert {
+ private Assert() {}
+
+ public static void fail(string message = "") throws AssertionError {
+ throw new AssertionError.FAILED(message);
+ }
+
+ public static void assert_true(bool condition) throws AssertionError {
+ if (!condition) { fail("Condition != true"); }
+ }
+
+ public static void assert_false(bool condition) throws AssertionError {
+ if (condition) { fail("Condition != false"); }
+ }
+
+ public static void assert_same(void* expected, void* actual) throws AssertionError {
+ if (expected != actual) { fail("expected == actual"); }
+ }
+
+ public static void assert_not_same(void* unexpected, void* actual) throws AssertionError {
+ if (unexpected == actual) { fail("unexpected != actual"); }
+ }
+
+ public static void assert_null(void* o) throws AssertionError {
+ if (o != null) { fail("Object is not null"); }
+ }
+
+ public static void assert_not_null(void* o) throws AssertionError {
+ if (o == null) { fail("Object is null"); }
+ }
+
+ public static void assert_equals(T expected, T actual) throws AssertionError {
+ var f = Gee.Functions.get_equal_func_for(typeof(T));
+ if (!f(expected, actual)) { fail("expected != actual"); }
+ }
+
+ public static void assert_not_equals(T unexpected, T actual) throws AssertionError {
+ var f = Gee.Functions.get_equal_func_for(typeof(T));
+ if (f(unexpected, actual)) { fail("expected == actual"); }
+ }
+ }
+}
diff --git a/src/testing/util/MockFramework.vala b/src/testing/util/MockFramework.vala
new file mode 100644
index 0000000..5b6ad26
--- /dev/null
+++ b/src/testing/util/MockFramework.vala
@@ -0,0 +1,529 @@
+/*
+ * MockFramework.vala
+ *
+ * Copyright (C) 2018 Venom authors and contributors
+ *
+ * This file is part of Venom.
+ *
+ * Venom is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Venom is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Venom. If not, see .
+ */
+
+public errordomain MatcherError {
+ CALL_COUNT_MISMATCH,
+ OBJECT_MISMATCH
+}
+
+namespace Mock {
+ public static Mock mock() {
+ return MockImpl.get_instance();
+ }
+
+ public static MockFunctionCall when(GLib.Object object, string function_name, Arguments args = new Arguments()) {
+ return mock().when(object, function_name, args);
+ }
+
+ public static void verify(GLib.Object object, string function_name, Arguments args = new Arguments()) throws MatcherError {
+ mock().verify(object, function_name, args);
+ }
+
+ public static void verify_count(GLib.Object object, string function_name, int count, Arguments args = new Arguments()) throws MatcherError {
+ mock().verify_count(object, function_name, count, args);
+ }
+
+ public static Arguments.ArgBuilder args() {
+ return Arguments.builder();
+ }
+
+ public static Matcher any_string() {
+ return new AnyStringMatcher();
+ }
+
+ private static string get_object_info(GLib.Object o) {
+ if (o == null) {
+ return "unknown";
+ }
+ return "%s".printf(o.get_type().name());
+ }
+
+ public interface Matcher : GLib.Object {
+ public abstract bool equals(GLib.Value v1, GLib.Value v2);
+ }
+
+ public class ValueMatcher : Matcher, GLib.Object {
+ public bool equals(GLib.Value v1, GLib.Value v2) {
+ var t1 = v1.type();
+ var t2 = v2.type();
+ if (t1 != t2) {
+ return false;
+ }
+ if (t1 == typeof(uint)) {
+ return v1.get_uint() == v2.get_uint();
+ } else if (t1 == typeof(int)) {
+ return v1.get_int() == v2.get_int();
+ } else if (t1 == typeof(uint64)) {
+ return v1.get_uint64() == v2.get_uint64();
+ } else if (t1 == typeof(int64)) {
+ return v1.get_int64() == v2.get_int64();
+ } else if (t1 == typeof(string)) {
+ return v1.get_string() == v2.get_string();
+ } else if (t1 == typeof(GLib.Object)) {
+ return v1.get_object() == v2.get_object();
+ } else if (t1 == typeof(bool)) {
+ return v1.get_boolean() == v2.get_boolean();
+ }
+ return false;
+ }
+ }
+
+ public class AnyStringMatcher : Matcher, GLib.Object {
+ public bool equals(GLib.Value v1, GLib.Value v2) {
+ var t1 = v1.type();
+ var t2 = v2.type();
+ return (t1 == t2 && t1 == typeof (string));
+ }
+ }
+
+ public class Argument : GLib.Object {
+ private GLib.Value value;
+ private Matcher matcher;
+
+ public Argument(GLib.Value value, Matcher matcher = new ValueMatcher()) {
+ this.value = value;
+ this.matcher = matcher;
+ }
+
+ public bool equals(Argument arg) {
+ return matcher.equals(value, arg.value);
+ }
+
+ public GLib.Value get_value() {
+ return value;
+ }
+ }
+
+ public class Arguments : GLib.Object {
+ private Gee.List arg_list;
+ construct {
+ arg_list = new Gee.ArrayList();
+ }
+
+ public void add(Argument arg) {
+ arg_list.add(arg);
+ }
+
+ public uint length() {
+ return arg_list.size;
+ }
+
+ public bool equals(Arguments args){
+ if (length() != args.length()) {
+ return false;
+ }
+ for (var i = 0; i < length(); i++) {
+ if (!arg_list.@get(i).equals(args.arg_list.@get(i))) {
+ return false;
+ }
+ }
+ return true;
+ }
+
+ const string uint64fmt = "%" + uint64.FORMAT_MODIFIER + "d";
+ const string int64fmt = "%" + int64.FORMAT_MODIFIER + "d";
+
+ public string to_string() {
+ var ret = "";
+ foreach (var arg in arg_list) {
+ var v = arg.get_value();
+ var t = v.type();
+ if (t == typeof(uint)) {
+ ret += " + (uint) %u\n".printf(v.get_uint());
+ } else if (t == typeof(int)) {
+ ret += " + (int) %i\n".printf(v.get_int());
+ } else if (t == typeof(uint64)) {
+ ret += " + (uint64) " + uint64fmt.printf(v.get_uint64()) + "\n";
+ } else if (t == typeof(int64)) {
+ ret += " + (int64) " + int64fmt.printf(v.get_int64()) + "\n";
+ } else if (t == typeof(string)) {
+ ret += " + (string) \"%s\"\n".printf(v.get_string());
+ } else if (t == typeof(GLib.Object)) {
+ ret += " + (Object) %s\n".printf(get_object_info(v.get_object()));
+ } else if (t == typeof(bool)) {
+ ret += " + (bool) %s\n".printf(v.get_boolean() ? "true" : "false");
+ }
+ }
+ return ret;
+ }
+
+ public static ArgBuilder builder() {
+ return new ArgBuilder();
+ }
+
+ public class ArgBuilder : GLib.Object {
+ private Arguments args;
+ construct {
+ args = new Arguments();
+ }
+ public ArgBuilder bool(bool b, Matcher m = new ValueMatcher()) {
+ var v = GLib.Value(typeof(bool));
+ v.set_boolean(b);
+ args.add(new Argument(v, m));
+ return this;
+ }
+ public ArgBuilder int(int i, Matcher m = new ValueMatcher()) {
+ var v = GLib.Value(typeof(int));
+ v.set_int(i);
+ args.add(new Argument(v, m));
+ return this;
+ }
+ public ArgBuilder uint(uint i, Matcher m = new ValueMatcher()) {
+ var v = GLib.Value(typeof(uint));
+ v.set_uint(i);
+ args.add(new Argument(v, m));
+ return this;
+ }
+ public ArgBuilder int64(int64 i, Matcher m = new ValueMatcher()) {
+ var v = GLib.Value(typeof(int64));
+ v.set_int64(i);
+ args.add(new Argument(v, m));
+ return this;
+ }
+ public ArgBuilder uint64(uint64 i, Matcher m = new ValueMatcher()) {
+ var v = GLib.Value(typeof(uint64));
+ v.set_uint64(i);
+ args.add(new Argument(v, m));
+ return this;
+ }
+ public ArgBuilder string(string s, Matcher m = new ValueMatcher()) {
+ var v = GLib.Value(typeof(string));
+ v.set_string(s);
+ args.add(new Argument(v, m));
+ return this;
+ }
+ public ArgBuilder object(GLib.Object o, Matcher m = new ValueMatcher()) {
+ var v = GLib.Value(typeof(GLib.Object));
+ v.set_object(o);
+ args.add(new Argument(v, m));
+ return this;
+ }
+ public Arguments create() {
+ return args;
+ }
+ }
+ }
+
+ public interface Mock : GLib.Object {
+ public abstract MockFunctionCall when(GLib.Object object, string function_name, Arguments args = new Arguments());
+ public abstract void verify(GLib.Object object, string function_name, Arguments args = new Arguments()) throws MatcherError;
+ public abstract void verify_count(GLib.Object object, string function_name, int count, Arguments args = new Arguments()) throws MatcherError;
+
+ public abstract MockFunctionCall actual_call(GLib.Object object, string function_name, Arguments args = new Arguments());
+
+ public abstract MockFunctionCall expect_one_call(GLib.Object object, string function_name, Arguments args = new Arguments());
+ public abstract MockFunctionCall expect_calls(GLib.Object object, string function_name, int call_count, Arguments args = new Arguments());
+ public abstract void verify_no_more_interactions(GLib.Object object) throws MatcherError;
+
+ public abstract Mock check_expectations() throws MatcherError;
+ public abstract void clear();
+ }
+
+ public interface MockFunctionCall : GLib.Object {
+ public abstract MockFunctionCall with_parameter(string parameter_name, GLib.Object parameter);
+ public abstract MockFunctionCall with_int_parameter(string parameter_name, int parameter);
+
+ public abstract MockFunctionCall increment_call_count();
+ public abstract MockFunctionCall increment_expected_count();
+
+ public abstract int get_call_count();
+ public abstract int get_expected_count();
+
+ public abstract MockFunctionCall set_call_count(int count);
+ public abstract MockFunctionCall set_expected_count(int count);
+
+ public abstract GLib.Object get_function_object();
+
+ public abstract string get_function_name();
+ public abstract Arguments get_args();
+
+ public abstract void set_bool(bool value);
+ public abstract void set_string(string value);
+ public abstract void then_return_int(int value);
+ public abstract void then_return_object(GLib.Object o);
+ public abstract void then_throw(GLib.Error error);
+
+ public abstract bool get_bool() throws GLib.Error;
+ public abstract string get_string() throws GLib.Error;
+ public abstract int get_int() throws GLib.Error;
+ public abstract Object ? get_object() throws GLib.Error;
+
+ public abstract void get_throws() throws GLib.Error;
+
+ public abstract string to_string_expected();
+ public abstract string to_string_actual();
+ public abstract bool equals(GLib.Object o, string function_name, Arguments args);
+ }
+
+ private class MockImpl : GLib.Object, Mock {
+ private static Mock instance;
+
+ public static Mock get_instance() {
+ if (instance == null) {
+ instance = new MockImpl();
+ }
+ return instance;
+ }
+
+ private GLib.List function_calls;
+
+ public MockImpl() {
+ function_calls = new GLib.List();
+ }
+
+ private MockFunctionCall init_func(GLib.Object o, string function_name, Arguments args) {
+ foreach (var call in function_calls) {
+ if (call.equals(o, function_name, args)) {
+ return call;
+ }
+ }
+ var call = new MockFunctionCallImpl(o, function_name, args);
+ function_calls.prepend(call);
+ return call;
+ }
+
+ public virtual MockFunctionCall actual_call(GLib.Object object, string function_name, Arguments args = new Arguments()) {
+ return init_func(object, function_name, args).increment_call_count();
+ }
+
+ public virtual MockFunctionCall when(GLib.Object object, string function_name, Arguments args = new Arguments()) {
+ return init_func(object, function_name, args);
+ }
+
+ public virtual void verify(GLib.Object object, string function_name, Arguments args = new Arguments()) throws MatcherError {
+ verify_call(expect_one_call(object, function_name, args));
+ }
+
+ public virtual void verify_count(GLib.Object object, string function_name, int count, Arguments args = new Arguments()) throws MatcherError {
+ verify_call_count(expect_calls(object, function_name, count, args), count);
+ }
+
+ public virtual MockFunctionCall expect_one_call(GLib.Object object, string function_name, Arguments args = new Arguments()) {
+ return init_func(object, function_name, args).increment_expected_count();
+ }
+
+ public virtual MockFunctionCall expect_calls(GLib.Object object, string function_name, int call_count, Arguments args = new Arguments()) {
+ var function_call = init_func(object, function_name, args);
+ return function_call.set_expected_count(function_call.get_expected_count() + call_count);
+ }
+
+ private void print_call_info(MockFunctionCall call) {
+ stderr.printf("# FOR OBJECT typeof %s\n", get_object_info(call.get_function_object()));
+ stderr.printf("# EXPECTED calls:\n# %s\n%s\n", call.to_string_expected(), call.get_args().to_string());
+ stderr.printf("# ACTUAL calls:\n");
+ foreach (var c in function_calls) {
+ if (c.get_call_count() > 0 && c.get_function_object() == call.get_function_object()) {
+ stderr.printf("# %s\n%s",
+ c.to_string_actual(),
+ c.get_args().to_string());
+ }
+ }
+ stderr.printf("###\n");
+ }
+
+ private void print_expected_call_count_mismatch(MockFunctionCall call) {
+ stderr.printf("### Expected call count mismatch: ###\n");
+ print_call_info(call);
+ }
+
+ private void print_expected_object_mismatch(MockFunctionCall call) {
+ stderr.printf("### Expected object mismatch: ###\n");
+ print_call_info(call);
+ }
+
+ private void print_expected_call_missing(MockFunctionCall call) {
+ stderr.printf("### Expected call missing: ###\n");
+ print_call_info(call);
+ }
+
+ private void verify_call(MockFunctionCall call) throws MatcherError {
+ var count = call.get_expected_count();
+ verify_call_count(call, count > 0 ? count : -1);
+ }
+
+ private void verify_call_count(MockFunctionCall call, int expected_count) throws MatcherError {
+ if (expected_count == 0 && call.get_call_count() > 0) {
+ print_expected_call_count_mismatch(call);
+ throw new MatcherError.CALL_COUNT_MISMATCH("Call count mismatch");
+ } else if (expected_count > 0 && call.get_call_count() == 0) {
+ print_expected_call_missing(call);
+ throw new MatcherError.CALL_COUNT_MISMATCH("Call missing");
+ } else if (expected_count > call.get_call_count()) {
+ print_expected_call_count_mismatch(call);
+ throw new MatcherError.CALL_COUNT_MISMATCH("Call count mismatch");
+ }
+ }
+
+ public virtual Mock check_expectations() throws MatcherError {
+ // var keys = function_calls.get_keys();
+ // var vals = function_calls.get_values();
+ // for (var i = 0; i < keys.length(); i++) {
+ // verify_call(vals.nth_data(i));
+ // }
+ return this;
+ }
+
+ public virtual void verify_no_more_interactions(GLib.Object object) throws MatcherError {
+ foreach (var call in function_calls) {
+ if (call.get_function_object() == object && call.get_expected_count() != call.get_call_count()) {
+ print_expected_call_count_mismatch(call);
+ throw new MatcherError.CALL_COUNT_MISMATCH("Call count mismatch");
+ }
+ }
+ }
+
+ public virtual void clear() {
+ function_calls = new GLib.List();
+ }
+ }
+
+ private class MockFunctionCallImpl : GLib.Object, MockFunctionCall {
+ private GLib.Object object;
+ private string name;
+ private Arguments args;
+
+ private int call_count;
+ private int expected_count;
+ private GLib.Value ? val;
+ private GLib.Error ? error;
+
+ public MockFunctionCallImpl(GLib.Object object, string name, Arguments args) {
+ this.object = object;
+ this.name = name;
+ this.args = args;
+ }
+
+ public virtual MockFunctionCall on_object(GLib.Object object) {
+ this.object = object;
+ return this;
+ }
+
+ public virtual MockFunctionCall with_parameter(string parameter_name, GLib.Object parameter) {
+ return this;
+ }
+
+ public virtual MockFunctionCall with_int_parameter(string parameter_name, int parameter) {
+ return this;
+ }
+
+ public virtual MockFunctionCall increment_call_count() {
+ call_count++;
+ return this;
+ }
+
+ public virtual MockFunctionCall increment_expected_count() {
+ expected_count++;
+ return this;
+ }
+
+ public virtual int get_call_count() {
+ return call_count;
+ }
+
+ public virtual int get_expected_count() {
+ return expected_count;
+ }
+
+ public virtual MockFunctionCall set_call_count(int count) {
+ call_count = count;
+ return this;
+ }
+
+ public virtual MockFunctionCall set_expected_count(int count) {
+ expected_count = count;
+ return this;
+ }
+
+ public virtual GLib.Object get_function_object() {
+ return object;
+ }
+
+ public virtual string get_function_name() {
+ return name;
+ }
+
+ public virtual Arguments get_args() {
+ return args;
+ }
+
+ public virtual void set_bool(bool value) {
+ val = Value(typeof(bool));
+ val.set_boolean(value);
+ }
+
+ public virtual void set_string(string value) {
+ val = Value(typeof(string));
+ val.set_string(value);
+ }
+
+ public virtual void then_return_int(int value) {
+ val = Value(typeof(int));
+ val.set_int(value);
+ }
+
+ public virtual void then_return_object(GLib.Object value) {
+ val = Value(typeof(GLib.Object));
+ val.set_object(value);
+ }
+
+ public virtual void then_throw(GLib.Error error) {
+ this.error = error;
+ }
+
+ public virtual bool get_bool() throws GLib.Error {
+ get_throws();
+ return val != null ? val.get_boolean() : false;
+ }
+
+ public virtual string get_string() throws GLib.Error {
+ get_throws();
+ return val != null ? val.get_string() : "";
+ }
+
+ public virtual int get_int() throws GLib.Error {
+ get_throws();
+ return val != null ? val.get_int() : 0;
+ }
+
+ public virtual Object ? get_object() throws GLib.Error {
+ get_throws();
+ return val != null ? val.get_object() : null;
+ }
+
+ public virtual void get_throws() throws GLib.Error {
+ if (error != null) {
+ throw error;
+ }
+ }
+
+ public virtual string to_string_expected() {
+ return "function(\"%s\") x%i".printf(name, expected_count);
+ }
+
+ public virtual string to_string_actual() {
+ return "function(\"%s\") x%i".printf(name, call_count);
+ }
+
+ public virtual bool equals(GLib.Object o, string function_name, Arguments args) {
+ return this.object == o && this.name == function_name && this.args.equals(args);
+ }
+ }
+}
diff --git a/src/testing/util/UnitTest.vala b/src/testing/util/UnitTest.vala
new file mode 100644
index 0000000..69ba2ec
--- /dev/null
+++ b/src/testing/util/UnitTest.vala
@@ -0,0 +1,64 @@
+/*
+ * UnitTest.vala
+ *
+ * Copyright (C) 2018 Venom authors and contributors
+ *
+ * This file is part of Venom.
+ *
+ * Venom is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Venom is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Venom. If not, see .
+ */
+
+namespace Testing {
+ public class UnitTest : GLib.Object {
+ public delegate void TestFunction() throws Error;
+ public void add_func(string name, TestFunction f) {
+ Test.add_data_func("/" + name, () => {
+ run_testcase(f);
+ });
+ }
+
+ public void run() {
+ Test.run();
+ }
+
+ private void run_testcase(TestFunction f) {
+ pre_set_up();
+ try {
+ set_up();
+ try {
+ f();
+ } catch (Error e) {
+ stderr.printf("# Testcase failed: %s\n", e.message);
+ Test.fail();
+ }
+ tear_down();
+ } catch (Error e) {
+ stderr.printf("# Error during test set_up/tear_down: %s\n", e.message);
+ Test.fail();
+ }
+ post_tear_down();
+ }
+
+ private void pre_set_up() {
+ Mock.mock().clear();
+ }
+
+ public virtual void set_up() throws Error {}
+ public virtual void tear_down() throws Error {}
+
+ private void post_tear_down() {
+ Mock.mock().clear();
+ }
+ }
+}
diff --git a/src/tox/Conference.vala b/src/tox/Conference.vala
new file mode 100644
index 0000000..a40a3ae
--- /dev/null
+++ b/src/tox/Conference.vala
@@ -0,0 +1,105 @@
+/*
+ * Conference.vala
+ *
+ * Copyright (C) 2013-2018 Venom authors and contributors
+ *
+ * This file is part of Venom.
+ *
+ * Venom is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Venom is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Venom. If not, see .
+ */
+
+namespace Venom {
+ public class Conference : IContact, GLib.Object {
+ // Saved in toxs savefile
+ public uint32 conference_number { get; set; }
+ public string title { get; set; }
+ public string status_message { get; set; default = ""; }
+ public int unread_messages { get; set; default = 0; }
+ public bool _show_notifications { get; set; default = true; }
+ private Gee.Map peers;
+ private static Gdk.Pixbuf default_image;
+
+ public Conference(uint32 conference_number, string title) {
+ this.conference_number = conference_number;
+ this.title = title;
+ peers = new Gee.HashMap();
+ }
+
+ public string get_id() {
+ return @"tox.conference.$conference_number";
+ }
+
+ public string get_name_string() {
+ return title != "" ? title : _("Unnamed conference %u").printf(conference_number);
+ }
+
+ public string get_status_string() {
+ return _("%u Peers online").printf(peers.size);
+ }
+
+ public UserStatus get_status() {
+ return UserStatus.NONE;
+ }
+
+ public bool is_connected() {
+ return !peers.is_empty;
+ }
+
+ public bool is_typing() {
+ return false;
+ }
+
+ public bool is_conference() {
+ return true;
+ }
+
+ public Gdk.Pixbuf get_image() {
+ if (default_image == null) {
+ try {
+ default_image = Gtk.IconTheme.get_default().load_icon(R.icons.default_groupchat, 48, 0);
+ } catch (Error e) {
+ assert_not_reached();
+ }
+ }
+ return default_image;
+ }
+
+ public unowned Gee.Map get_peers() {
+ return peers;
+ }
+
+ public bool show_notifications() {
+ return _show_notifications;
+ }
+
+ public bool get_requires_attention() { return unread_messages > 0; }
+ public void clear_attention() { unread_messages = 0; }
+ }
+
+ public class ConferencePeer : GLib.Object {
+ public uint32 peer_number { get; set; }
+ public string peer_key { get; set; }
+ public string peer_name { get; set; }
+ public bool is_known { get; set; }
+ public bool is_self { get; set; }
+
+ public ConferencePeer(uint32 peer_number, string peer_key, string peer_name, bool is_known, bool is_self) {
+ this.peer_number = peer_number;
+ this.peer_key = peer_key;
+ this.peer_name = peer_name;
+ this.is_known = is_known;
+ this.is_self = is_self;
+ }
+ }
+}
diff --git a/src/tox/ConferenceMessage.vala b/src/tox/ConferenceMessage.vala
new file mode 100644
index 0000000..0ba0065
--- /dev/null
+++ b/src/tox/ConferenceMessage.vala
@@ -0,0 +1,90 @@
+/*
+ * ConferenceMessage.vala
+ *
+ * Copyright (C) 2018 Venom authors and contributors
+ *
+ * This file is part of Venom.
+ *
+ * Venom is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Venom is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Venom. If not, see .
+ */
+
+namespace Venom {
+ public class ConferenceMessage : IMessage, Object {
+ public GLib.DateTime timestamp { get; protected set; }
+ public MessageDirection message_direction { get; protected set; }
+ public bool important { get; set; }
+ public bool is_action { get; set; }
+ public bool received { get; set; }
+
+ public uint32 conference_number { get; protected set; }
+ public string message { get; protected set; }
+ public string peer_name { get; protected set; }
+ public string peer_key { get; protected set; }
+
+ private ConferenceMessage(uint32 conference_number, MessageDirection direction, string message, GLib.DateTime timestamp) {
+ this.conference_number = conference_number;
+ this.message_direction = direction;
+ this.message = message;
+ this.timestamp = timestamp;
+ this.important = false;
+ this.is_action = false;
+ }
+
+ public ConferenceMessage.outgoing(uint32 conference_number, string message, GLib.DateTime timestamp = new GLib.DateTime.now_local()) {
+ this(conference_number, MessageDirection.OUTGOING, message, timestamp);
+ }
+
+ public ConferenceMessage.incoming(uint32 conference_number, string peer_key, string peer_name, string message, GLib.DateTime timestamp = new GLib.DateTime.now_local()) {
+ this(conference_number, MessageDirection.INCOMING, message, timestamp);
+ this.peer_key = peer_key;
+ this.peer_name = peer_name;
+ }
+
+ public string get_sender_plain() {
+ if (message_direction == MessageDirection.OUTGOING) {
+ return _("me");
+ } else {
+ return peer_name;
+ }
+ }
+
+ public string get_conversation_id() {
+ return @"tox.conference.$conference_number";
+ }
+
+ public string get_sender_id() {
+ return peer_key;
+ }
+
+ public string get_message_plain() {
+ return message;
+ }
+
+ public string get_time_plain() {
+ return timestamp.format("%c");
+ }
+
+ public bool is_conference_message() {
+ return true;
+ }
+
+ public Gdk.Pixbuf get_sender_image() {
+ return pixbuf_from_resource(R.icons.default_contact);
+ }
+
+ public bool equals_sender(IMessage m) {
+ return m is ConferenceMessage && ((ConferenceMessage) m).peer_key == peer_key;
+ }
+ }
+}
diff --git a/src/tox/ContactDatabase.vala b/src/tox/ContactDatabase.vala
new file mode 100644
index 0000000..8589be8
--- /dev/null
+++ b/src/tox/ContactDatabase.vala
@@ -0,0 +1,122 @@
+/*
+ * ContactDatabase.vala
+ *
+ * Copyright (C) 2013-2017 Venom authors and contributors
+ *
+ * This file is part of Venom.
+ *
+ * Venom is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Venom is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Venom. If not, see .
+ */
+
+namespace Venom {
+ public class SqliteContactDatabase : IContactDatabase, Object {
+ private const string QUERY_TABLE_CONTACTS = """
+ CREATE TABLE IF NOT EXISTS Contacts (
+ id INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL,
+ key TEXT NOT NULL UNIQUE,
+ note TEXT NOT NULL,
+ alias TEXT NOT NULL,
+ isblocked INTEGER NOT NULL,
+ ingroup TEXT NOT NULL
+ );
+ """;
+ private enum ContactColumn {
+ ID,
+ KEY,
+ NOTE,
+ ALIAS,
+ ISBLOCKED,
+ GROUP
+ }
+
+ private const string TABLE_KEY = "$KEY";
+ private const string TABLE_NOTE = "$NOTE";
+ private const string TABLE_ALIAS = "$ALIAS";
+ private const string TABLE_ISBLOCKED = "$ISBLOCKED";
+ private const string TABLE_GROUP = "$GROUP";
+
+ private static string STATEMENT_INSERT_CONTACT = "INSERT OR REPLACE INTO Contacts (key, note, alias, isblocked, ingroup) VALUES (%s, %s, %s, %s, %s);".printf(TABLE_KEY, TABLE_NOTE, TABLE_ALIAS, TABLE_ISBLOCKED, TABLE_GROUP);
+ private static string STATEMENT_SELECT_CONTACT = "SELECT * FROM Contacts WHERE key = %s".printf(TABLE_KEY);
+ private static string STATEMENT_DELETE_CONTACT = "DELETE FROM Contacts WHERE key = %s".printf(TABLE_KEY);
+
+ private IDatabaseStatement insertStatement;
+ private IDatabaseStatement selectStatement;
+ private IDatabaseStatement deleteStatement;
+ private ILogger logger;
+
+ public SqliteContactDatabase(IDatabaseStatementFactory statementFactory, ILogger logger) throws DatabaseStatementError {
+ this.logger = logger;
+ statementFactory
+ .createStatement(QUERY_TABLE_CONTACTS)
+ .step();
+
+ insertStatement = statementFactory.createStatement(STATEMENT_INSERT_CONTACT);
+ selectStatement = statementFactory.createStatement(STATEMENT_SELECT_CONTACT);
+ deleteStatement = statementFactory.createStatement(STATEMENT_DELETE_CONTACT);
+
+ logger.d("SqliteContactDatabase created.");
+ }
+
+ ~SqliteContactDatabase() {
+ logger.d("SqliteContactDatabase destroyed.");
+ }
+
+ public void loadContactData(string userId, IContactData contactData) {
+ try {
+ selectStatement.bind_text(TABLE_KEY, userId);
+
+ if (selectStatement.step() == Sqlite.ROW) {
+ var note = selectStatement.column_text(ContactColumn.NOTE);
+ var alias = selectStatement.column_text(ContactColumn.ALIAS);
+ var isBlocked = selectStatement.column_bool(ContactColumn.ISBLOCKED);
+ var group = selectStatement.column_text(ContactColumn.GROUP);
+ contactData.saveContactData(note, alias, isBlocked, group);
+ }
+ } catch (DatabaseStatementError e) {
+ logger.e("Error reading contact information from sqlite database: " + e.message);
+ }
+
+ selectStatement.reset();
+ }
+
+ public void saveContactData(string userId, string note, string alias, bool isBlocked, string group) {
+ try {
+ insertStatement.builder()
+ .bind_text(TABLE_KEY, userId)
+ .bind_text(TABLE_NOTE, note)
+ .bind_text(TABLE_ALIAS, alias)
+ .bind_bool(TABLE_ISBLOCKED, isBlocked)
+ .bind_text(TABLE_GROUP, group)
+ .step();
+ } catch (DatabaseStatementError e) {
+ logger.e("Error writing contact information to sqlite database: " + e.message);
+ } finally {
+ insertStatement.reset();
+ }
+ }
+
+ public void deleteContactData(string userId) {
+ try {
+ deleteStatement.builder()
+ .bind_text(TABLE_KEY, userId)
+ .step();
+ } catch (DatabaseStatementError e) {
+ logger.e("Error deleting contact information in sqlite database: " + e.message);
+ } finally {
+ deleteStatement.reset();
+ }
+ }
+
+ }
+}
diff --git a/src/tox/DhtNode.vala b/src/tox/DhtNode.vala
new file mode 100644
index 0000000..50261b4
--- /dev/null
+++ b/src/tox/DhtNode.vala
@@ -0,0 +1,46 @@
+/*
+ * DhtNode.vala
+ *
+ * Copyright (C) 2013-2017 Venom authors and contributors
+ *
+ * This file is part of Venom.
+ *
+ * Venom is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Venom is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Venom. If not, see .
+ */
+
+namespace Venom {
+ public class DhtNodeFactory : IDhtNodeFactory, Object {
+ public IDhtNode createDhtNode(string key, string address, uint port, bool is_blocked, string owner, string location) {
+ return new DhtNode(key, address, port, is_blocked, owner, location);
+ }
+ }
+
+ public class DhtNode : IDhtNode, Object {
+ public string pub_key { get; set; }
+ public string host { get; set; }
+ public uint port { get; set; }
+ public bool is_blocked { get; set; }
+ public string maintainer { get; set; }
+ public string location { get; set; }
+
+ public DhtNode(string pub_key, string host, uint port = 33445, bool is_blocked = false, string maintainer = "", string location = "") {
+ this.pub_key = pub_key;
+ this.host = host;
+ this.port = port;
+ this.is_blocked = is_blocked;
+ this.maintainer = maintainer;
+ this.location = location;
+ }
+ }
+}
diff --git a/src/tox/DhtNodeDatabase.vala b/src/tox/DhtNodeDatabase.vala
new file mode 100644
index 0000000..d9bd1ab
--- /dev/null
+++ b/src/tox/DhtNodeDatabase.vala
@@ -0,0 +1,48 @@
+/*
+ * DhtNodeDatabase.vala
+ *
+ * Copyright (C) 2013-2017 Venom authors and contributors
+ *
+ * This file is part of Venom.
+ *
+ * Venom is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Venom is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Venom. If not, see .
+ */
+
+namespace Venom {
+ public class StaticDhtNodeDatabase : IDhtNodeDatabase, Object {
+ public List getDhtNodes(IDhtNodeFactory nodeFactory) {
+ var nodes = new List();
+ nodes.append(nodeFactory.createDhtNode(
+ "461FA3776EF0FA655F1A05477DF1B3B614F7D6B124F7DB1DD4FE3C08B03B640F",
+ "130.133.110.14",
+ 33445,
+ false,
+ "manolis",
+ "DE"
+ ));
+ nodes.append(nodeFactory.createDhtNode(
+ "F404ABAA1C99A9D37D61AB54898F56793E1DEF8BD46B1038B9D822E8460FAB67",
+ "node.tox.biribiri.org",
+ 33445,
+ false,
+ "nurupo",
+ "US"
+ ));
+
+ return nodes;
+ }
+ public void insertDhtNode(string key, string address, uint port, bool isBlocked, string owner, string location) {}
+ public void deleteDhtNode(string key) {}
+ }
+}
diff --git a/src/tox/FriendRequest.vala b/src/tox/FriendRequest.vala
new file mode 100644
index 0000000..c4ba4c0
--- /dev/null
+++ b/src/tox/FriendRequest.vala
@@ -0,0 +1,46 @@
+/*
+ * FriendRequest.vala
+ *
+ * Copyright (C) 2018 Venom authors and contributors
+ *
+ * This file is part of Venom.
+ *
+ * Venom is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Venom is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Venom. If not, see .
+ */
+
+namespace Venom {
+ public class FriendRequest : GLib.Object {
+ public string id { get; set; }
+ public string message { get; set; }
+
+ public FriendRequest(string id, string message) {
+ this.id = id;
+ this.message = message;
+ }
+ }
+
+ public class ConferenceInvite : GLib.Object {
+ public IContact sender { get; set; }
+ public ConferenceType conference_type { get; set; }
+ public uint8[] get_cookie() {
+ return cookie;
+ }
+ private uint8[] cookie;
+ public ConferenceInvite(IContact sender, ConferenceType conference_type, uint8[] cookie) {
+ this.sender = sender;
+ this.conference_type = conference_type;
+ this.cookie = cookie;
+ }
+ }
+}
diff --git a/src/tox/JsonWebDhtNodeDatabase.vala b/src/tox/JsonWebDhtNodeDatabase.vala
new file mode 100644
index 0000000..1cbf7b2
--- /dev/null
+++ b/src/tox/JsonWebDhtNodeDatabase.vala
@@ -0,0 +1,80 @@
+/*
+ * JsonWebDhtNodeDatabase.vala
+ *
+ * Copyright (C) 2017 Venom authors and contributors
+ *
+ * This file is part of Venom.
+ *
+ * Venom is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Venom is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Venom. If not, see .
+ */
+
+namespace Venom {
+ public class JsonDhtNode : GLib.Object {
+ public string ipv4 { get; set; }
+ public string ipv6 { get; set; }
+ public int port { get; set; }
+ //public int[] tcp_ports { get; set; }
+ public string public_key { get; set; }
+ public string maintainer { get; set; }
+ public string location { get; set; }
+ public bool status_udp { get; set; }
+ public bool status_tcp { get; set; }
+ public string version { get; set; }
+ public string motd { get; set; }
+ public int last_ping { get; set; }
+ }
+
+ public class JsonWebDhtNodeDatabase : IDhtNodeDatabase, GLib.Object {
+ private ILogger logger;
+ public JsonWebDhtNodeDatabase(ILogger logger) {
+ this.logger = logger;
+ }
+ public List getDhtNodes(IDhtNodeFactory factory) {
+ var dhtNodes = new List();
+
+ var uri = "https://nodes.tox.chat/json";
+
+ var session = new Soup.Session();
+ var message = new Soup.Message("GET", uri);
+ session.send_message(message);
+
+ try {
+ var parser = new Json.Parser();
+ parser.load_from_data((string) message.response_body.flatten().data);
+ var root_object = parser.get_root().get_object();
+ //var last_scan = (uint) root_object.get_int_member("last_scan");
+ //var last_refresh = (uint) root_object.get_int_member("last_refresh");
+
+ var nodes = root_object.get_array_member("nodes");
+ foreach (var node in nodes.get_elements()) {
+ var json_node = Json.gobject_deserialize(typeof(JsonDhtNode), node) as JsonDhtNode;
+ if (json_node.ipv4 != "-") {
+ dhtNodes.append(factory.createDhtNode(json_node.public_key, json_node.ipv4, json_node.port, false, json_node.maintainer, json_node.location));
+ }
+ //FIXME allow multiple addresses per pubkey in node database
+ // if (json_node.ipv6 != "-") {
+ // dhtNodes.append(factory.createDhtNode(json_node.public_key, json_node.ipv6, json_node.port, false, json_node.maintainer, json_node.location));
+ // }
+
+ }
+ } catch (Error e) {
+ logger.e("Failed to load dht nodes from uri: " + e.message);
+ }
+ return dhtNodes;
+ }
+
+ public void insertDhtNode(string key, string address, uint port, bool isBlocked, string owner, string location) {}
+ public void deleteDhtNode(string key) {}
+ }
+}
diff --git a/src/tox/MessageDatabase.vala b/src/tox/MessageDatabase.vala
new file mode 100644
index 0000000..c7c8b77
--- /dev/null
+++ b/src/tox/MessageDatabase.vala
@@ -0,0 +1,128 @@
+/*
+ * MessageDatabase.vala
+ *
+ * Copyright (C) 2013-2017 Venom authors and contributors
+ *
+ * This file is part of Venom.
+ *
+ * Venom is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Venom is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Venom. If not, see .
+ */
+
+namespace Venom {
+ public class SqliteMessageDatabase : IMessageDatabase, Object {
+ private enum HistoryColumn {
+ ID,
+ USER,
+ CONTACT,
+ MESSAGE,
+ TIME,
+ SENDER
+ }
+
+ private const string TABLE_USER = "$USER";
+ private const string TABLE_CONTACT = "$CONTACT";
+ private const string TABLE_MESSAGE = "$MESSAGE";
+ private const string TABLE_TIME = "$TIME";
+ private const string TABLE_SENDER = "$SENDER";
+
+ private string STATEMENT_INSERT_HISTORY = "INSERT INTO History (userHash, contactHash, message, timestamp, issent) VALUES (%s, %s, %s, %s, %s);".printf(TABLE_USER, TABLE_CONTACT, TABLE_MESSAGE, TABLE_TIME, TABLE_SENDER);
+ private string STATEMENT_SELECT_HISTORY = "SELECT * FROM History WHERE userHash = %s AND contactHash = %s;".printf(TABLE_USER, TABLE_CONTACT);
+ private string STATEMENT_SANITIZE_DATABASE = "DELETE FROM History WHERE timestamp < %s;".printf(TABLE_TIME);
+
+ private const string QUERY_TABLE_HISTORY = """
+ CREATE TABLE IF NOT EXISTS History (
+ id INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL,
+ userHash TEXT NOT NULL,
+ contactHash TEXT NOT NULL,
+ message TEXT NOT NULL,
+ timestamp INTEGER NOT NULL,
+ issent INTEGER NOT NULL
+ );
+ """;
+
+ private ILogger logger;
+
+ private IDatabaseStatement insertStatement;
+ private IDatabaseStatement selectStatement;
+ private IDatabaseStatement sanitizeStatement;
+
+ public SqliteMessageDatabase(IDatabaseStatementFactory statementFactory, ILogger logger) throws DatabaseStatementError {
+ this.logger = logger;
+
+ statementFactory
+ .createStatement(QUERY_TABLE_HISTORY)
+ .step();
+
+ insertStatement = statementFactory.createStatement(STATEMENT_INSERT_HISTORY);
+ selectStatement = statementFactory.createStatement(STATEMENT_SELECT_HISTORY);
+ sanitizeStatement = statementFactory.createStatement(STATEMENT_SANITIZE_DATABASE);
+ logger.d("SQLite database created.");
+ }
+
+ ~SqliteMessageDatabase() {
+ logger.d("SQLite database closed.");
+ }
+
+ public void insertMessage(string userId, string contactId, string message, DateTime time, bool outgoing) {
+ try {
+ insertStatement.builder()
+ .bind_text(TABLE_USER, userId)
+ .bind_text(TABLE_CONTACT, contactId)
+ .bind_text(TABLE_MESSAGE, message)
+ .bind_int64(TABLE_TIME, time.to_unix())
+ .bind_bool(TABLE_SENDER, outgoing)
+ .step();
+ } catch (DatabaseStatementError e) {
+ logger.e("Error writing message to database: " + e.message);
+ } finally {
+ insertStatement.reset();
+ }
+ }
+
+ public List retrieveMessages(string userId, string contactId, ILoggedMessageFactory messageFactory) {
+ var messages = new List();
+ try {
+ selectStatement.builder()
+ .bind_text(TABLE_USER, userId)
+ .bind_text(TABLE_CONTACT, contactId);
+
+ while (selectStatement.step() == DatabaseResult.ROW) {
+ var messageString = selectStatement.column_text(HistoryColumn.MESSAGE);
+ var timestamp = selectStatement.column_int64(HistoryColumn.TIME);
+ var outgoing = selectStatement.column_bool(HistoryColumn.SENDER);
+ var sendTime = new DateTime.from_unix_local(timestamp);
+ var message = messageFactory.createLoggedMessage(userId, contactId, messageString, sendTime, outgoing);
+ messages.append(message);
+ }
+ } catch (DatabaseStatementError e) {
+ logger.e("Error retrieving messages from database: " + e.message);
+ } finally {
+ selectStatement.reset();
+ }
+ return messages;
+ }
+
+ public void deleteMessagesBefore(DateTime date) {
+ try {
+ sanitizeStatement.builder()
+ .bind_int64(TABLE_TIME, date.to_unix())
+ .step();
+ } catch (DatabaseStatementError e) {
+ logger.e("Error sanitizing database: " + e.message);
+ } finally {
+ sanitizeStatement.reset();
+ }
+ }
+ }
+}
diff --git a/src/tox/SqliteDhtNodeDatabase.vala b/src/tox/SqliteDhtNodeDatabase.vala
new file mode 100644
index 0000000..f451932
--- /dev/null
+++ b/src/tox/SqliteDhtNodeDatabase.vala
@@ -0,0 +1,130 @@
+/*
+ * SqliteDhtNodeDatabase.vala
+ *
+ * Copyright (C) 2017-2018 Venom authors and contributors
+ *
+ * This file is part of Venom.
+ *
+ * Venom is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Venom is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Venom. If not, see .
+ */
+
+namespace Venom {
+ public class SqliteDhtNodeDatabase : IDhtNodeDatabase, Object {
+ private const string CREATE_TABLE_NODES = """
+ CREATE TABLE IF NOT EXISTS Nodes (
+ id INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL,
+ key TEXT NOT NULL UNIQUE,
+ address TEXT NOT NULL,
+ port INTEGER NOT NULL,
+ isblocked INTEGER NOT NULL,
+ owner TEXT NOT NULL,
+ location TEXT NOT NULL
+ );
+ """;
+ private enum NodeColumn {
+ ID,
+ KEY,
+ ADDRESS,
+ PORT,
+ ISBLOCKED,
+ OWNER,
+ LOCATION
+ }
+
+ private const string TABLE_KEY = "$KEY";
+ private const string TABLE_ADDRESS = "$ADDRESS";
+ private const string TABLE_PORT = "$PORT";
+ private const string TABLE_ISBLOCKED = "$ISBLOCKED";
+ private const string TABLE_OWNER = "$OWNER";
+ private const string TABLE_LOCATION = "$LOCATION";
+
+ private static string STATEMENT_INSERT_NODE = "INSERT OR REPLACE INTO Nodes (key, address, port, isblocked, owner, location) VALUES (%s, %s, %s, %s, %s, %s);".printf(TABLE_KEY, TABLE_ADDRESS, TABLE_PORT, TABLE_ISBLOCKED, TABLE_OWNER, TABLE_LOCATION);
+ private static string STATEMENT_SELECT_NODES = "SELECT * FROM Nodes";
+ private static string STATEMENT_DELETE_NODE = "DELETE FROM Nodes WHERE key = %s".printf(TABLE_KEY);
+
+ private IDatabaseStatement insertStatement;
+ private IDatabaseStatement selectStatement;
+ private IDatabaseStatement deleteStatement;
+
+ private ILogger logger;
+
+ public SqliteDhtNodeDatabase(IDatabaseStatementFactory statementFactory, ILogger logger) throws DatabaseStatementError {
+ this.logger = logger;
+
+ statementFactory
+ .createStatement(CREATE_TABLE_NODES)
+ .step();
+
+ insertStatement = statementFactory.createStatement(STATEMENT_INSERT_NODE);
+ selectStatement = statementFactory.createStatement(STATEMENT_SELECT_NODES);
+ deleteStatement = statementFactory.createStatement(STATEMENT_DELETE_NODE);
+
+ logger.d("SqliteDhtNodeDatabase created.");
+ }
+
+ ~SqliteDhtNodeDatabase() {
+ logger.d("SqliteDhtNodeDatabase destroyed.");
+ }
+
+ public List getDhtNodes(IDhtNodeFactory nodeFactory) {
+ var dhtNodes = new List();
+ try {
+ while (selectStatement.step() == DatabaseResult.ROW) {
+ var key = selectStatement.column_text(NodeColumn.KEY);
+ var address = selectStatement.column_text(NodeColumn.ADDRESS);
+ var port = selectStatement.column_int(NodeColumn.PORT);
+ var isBlocked = selectStatement.column_bool(NodeColumn.ISBLOCKED);
+ var owner = selectStatement.column_text(NodeColumn.OWNER);
+ var location = selectStatement.column_text(NodeColumn.LOCATION);
+ var node = nodeFactory.createDhtNode(key, address, port, isBlocked, owner, location);
+ dhtNodes.append(node);
+ }
+ } catch (DatabaseStatementError e) {
+ logger.e("Could not read dht node from database: " + e.message);
+ } finally {
+ selectStatement.reset();
+ }
+ return dhtNodes;
+ }
+
+ public void insertDhtNode(string key, string address, uint port, bool isBlocked, string owner, string location) {
+ try {
+ insertStatement.builder()
+ .bind_text(TABLE_KEY, key)
+ .bind_text(TABLE_ADDRESS, address)
+ .bind_int(TABLE_PORT, (int) port)
+ .bind_bool(TABLE_ISBLOCKED, isBlocked)
+ .bind_text(TABLE_OWNER, owner)
+ .bind_text(TABLE_LOCATION, location)
+ .step();
+ } catch (DatabaseStatementError e) {
+ logger.e("Could not insert Dht Node into database: " + e.message);
+ } finally {
+ insertStatement.reset();
+ }
+ }
+
+ public void deleteDhtNode(string key) {
+ try {
+ deleteStatement.builder()
+ .bind_text(TABLE_KEY, key)
+ .step();
+ } catch (DatabaseStatementError e) {
+ logger.e("Could not delete Dht Node in database: " + e.message);
+ } finally {
+ deleteStatement.reset();
+ }
+ }
+ }
+}
diff --git a/src/tox/ToxAdapterConferenceListener.vala b/src/tox/ToxAdapterConferenceListener.vala
new file mode 100644
index 0000000..eaed165
--- /dev/null
+++ b/src/tox/ToxAdapterConferenceListener.vala
@@ -0,0 +1,204 @@
+/*
+ * ToxAdapterConferenceListener.vala
+ *
+ * Copyright (C) 2018 Venom authors and contributors
+ *
+ * This file is part of Venom.
+ *
+ * Venom is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Venom is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Venom. If not, see .
+ */
+
+namespace Venom {
+ public class ToxAdapterConferenceListenerImpl : ToxAdapterConferenceListener, ConferenceInviteEntryListener, ConferenceWidgetListener, ConferenceInfoWidgetListener, CreateGroupchatWidgetListener, GLib.Object {
+ private unowned ToxSession session;
+ private ILogger logger;
+ private ObservableList contacts;
+ private ObservableList conference_invites;
+ private NotificationListener notification_listener;
+ private GLib.HashTable conversations;
+
+ private GLib.HashTable conferences;
+ private unowned GLib.HashTable friends;
+
+ public ToxAdapterConferenceListenerImpl(ILogger logger, ObservableList contacts, ObservableList conference_invites, GLib.HashTable conversations, NotificationListener notification_listener) {
+ logger.d("ToxAdapterConferenceListenerImpl created.");
+ this.logger = logger;
+ this.contacts = contacts;
+ this.conference_invites = conference_invites;
+ this.conversations = conversations;
+ this.notification_listener = notification_listener;
+
+ conferences = new GLib.HashTable(null, null);
+ }
+
+ ~ToxAdapterConferenceListenerImpl() {
+ logger.d("ToxAdapterConferenceListenerImpl destroyed.");
+ }
+
+ public virtual void attach_to_session(ToxSession session) {
+ this.session = session;
+ session.set_conference_listener(this);
+ friends = session.get_friends();
+ }
+
+ public virtual void on_remove_conference(IContact c) throws Error {
+ var contact = c as Conference;
+ session.conference_delete(contact.conference_number);
+ }
+
+ public virtual void on_change_conference_title(IContact c, string title) throws Error {
+ var contact = c as Conference;
+ session.conference_set_title(contact.conference_number, title);
+ }
+
+ public virtual void on_send_conference_message(IContact c, string message) throws Error {
+ var conference = c as Conference;
+ session.conference_send_message(conference.conference_number, message);
+ }
+
+ public virtual void on_create_groupchat(string title, ConferenceType type) throws Error {
+ session.conference_new(title);
+ }
+
+ public virtual void on_send_conference_invite(IContact c, string id) throws Error {
+ logger.d("on_send_conference_invite");
+ if (c is Contact) {
+ var contact = c as Contact;
+ if (id == "") {
+ var conference_number = session.conference_new("");
+ session.conference_invite(contact.tox_friend_number, conference_number);
+ } else {
+ var index = id.last_index_of(".");
+ var conference_number = int.parse(id.substring(index + 1));
+ session.conference_invite(contact.tox_friend_number, conference_number);
+ }
+ } else {
+ assert_not_reached();
+ }
+ }
+
+ public virtual void on_accept_conference_invite(ConferenceInvite invite) throws Error {
+ var c = invite.sender as Contact;
+ session.conference_join(c.tox_friend_number, invite.conference_type, invite.get_cookie());
+ conference_invites.remove(invite);
+ }
+
+ public virtual void on_reject_conference_invite(ConferenceInvite invite) throws Error {
+ conference_invites.remove(invite);
+ }
+
+ private bool invite_equals(ConferenceInvite invite, uint32 friend_number, ConferenceType type, uint8[] cookie) {
+ var cmp_sender = invite.sender as Contact;
+ var cmp_cookie = invite.get_cookie();
+ return (cmp_sender.tox_friend_number == friend_number
+ && invite.conference_type == type
+ && cmp_cookie.length == cookie.length
+ && Memory.cmp(cookie, cmp_cookie, cookie.length) == 0);
+ }
+
+ public virtual void on_conference_invite_received(uint32 friend_number, ConferenceType type, uint8[] cookie) {
+ logger.d("on_conference_invite_received");
+
+ if (friend_number == uint32.MAX) {
+ session.conference_join(friend_number, type, cookie);
+ } else {
+ for (var i = 0; i < conference_invites.length(); i++) {
+ var invite = conference_invites.nth_data(i) as ConferenceInvite;
+ if (invite_equals(invite, friend_number, type, cookie)) {
+ logger.d("duplicate invite received, discarding");
+ return;
+ }
+ }
+
+ var contact = friends.@get(friend_number) as Contact;
+ if (contact.auto_conference) {
+ session.conference_join(friend_number, type, cookie);
+ } else {
+ var invite = new ConferenceInvite(contact, type, cookie);
+ conference_invites.append(invite);
+ }
+ }
+ }
+
+ public virtual void on_conference_new(uint32 conference_number, string title) {
+ logger.d("on_conference_new");
+ var contact = new Conference(conference_number, title);
+ contacts.append(contact);
+ conferences.@set(conference_number, contact);
+ var conversation = new ObservableList();
+ conversation.set_list(new GLib.List());
+ conversations.@set(contact, conversation);
+ }
+
+ public virtual void on_conference_deleted(uint32 conference_number) {
+ logger.d("on_conference_deleted");
+ var contact = conferences.@get(conference_number);
+ contacts.remove(contact);
+ conversations.remove(contact);
+ conferences.remove(conference_number);
+ }
+
+ public virtual void on_conference_title_changed(uint32 conference_number, uint32 peer_number, string title) {
+ var contact = conferences.@get(conference_number) as Conference;
+ contact.title = title;
+ contact.changed();
+ }
+
+ public virtual void on_conference_peer_list_changed(uint32 conference_number, ToxConferencePeer[] peers) {
+ var contact = conferences.@get(conference_number) as Conference;
+ var gcpeers = contact.get_peers();
+ gcpeers.clear();
+ for (var i = 0; i < peers.length; i++) {
+ var peer_number = peers[i].peer_number;
+ var peer_key = Tools.bin_to_hexstring(peers[i].peer_key);;
+ var peer = new ConferencePeer(peer_number, peer_key, peers[i].peer_name, peers[i].is_known, peers[i].is_self);
+ gcpeers.@set(peer_number, peer);
+ }
+ contact.changed();
+ }
+
+ public virtual void on_conference_peer_renamed(uint32 conference_number, ToxConferencePeer peer) {
+ var contact = conferences.@get(conference_number) as Conference;
+ var peers = contact.get_peers();
+ var peer_number = peer.peer_number;
+ var gcpeer = peers.@get(peer_number);
+ gcpeer.peer_key = Tools.bin_to_hexstring(peer.peer_key);
+ gcpeer.peer_name = peer.peer_name;
+ gcpeer.is_known = peer.is_known;
+ gcpeer.is_self = peer.is_self;
+ contact.changed();
+ }
+
+ public virtual void on_conference_message(uint32 conference_number, uint32 peer_number, ToxCore.MessageType type, string message) {
+ logger.d("on_conference_message");
+ var contact = conferences.@get(conference_number) as Conference;
+ var conversation = conversations.@get(contact);
+ var peer = contact.get_peers().@get(peer_number);
+ var msg = new ConferenceMessage.incoming(conference_number, peer.peer_key, peer.peer_name, message);
+ notification_listener.on_unread_message(msg, contact);
+ contact.unread_messages++;
+ contact.changed();
+ conversation.append(msg);
+ }
+
+ public virtual void on_conference_message_sent(uint32 conference_number, string message) {
+ logger.d("on_conference_message_sent");
+ var contact = conferences.@get(conference_number) as Conference;
+ var conversation = conversations.@get(contact);
+ var msg = new ConferenceMessage.outgoing(conference_number, message);
+ msg.received = true;
+ conversation.append(msg);
+ }
+ }
+}
diff --git a/src/tox/ToxAdapterFiletransferListener.vala b/src/tox/ToxAdapterFiletransferListener.vala
new file mode 100644
index 0000000..2dba2e8
--- /dev/null
+++ b/src/tox/ToxAdapterFiletransferListener.vala
@@ -0,0 +1,343 @@
+/*
+ * ToxAdapterFiletransferListener.vala
+ *
+ * Copyright (C) 2018 Venom authors and contributors
+ *
+ * This file is part of Venom.
+ *
+ * Venom is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Venom is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Venom. If not, see .
+ */
+
+namespace Venom {
+ public class ToxAdapterFiletransferListenerImpl : ToxAdapterFiletransferListener, FileTransferEntryListener, ConversationWidgetFiletransferListener, GLib.Object {
+ private const int MAX_AVATAR_SIZE = 64 * 1024;
+
+ private unowned ToxSession session;
+ private ILogger logger;
+ private NotificationListener notification_listener;
+
+ private unowned GLib.HashTable friends;
+ private Gee.Map > file_transfers;
+ private unowned GLib.HashTable conversations;
+
+ private ObservableList transfers;
+
+ public ToxAdapterFiletransferListenerImpl(ILogger logger, ObservableList transfers, GLib.HashTable conversations, NotificationListener notification_listener) {
+ logger.d("ToxAdapterFiletransferListenerImpl created.");
+ this.logger = logger;
+ this.transfers = transfers;
+ this.conversations = conversations;
+ this.notification_listener = notification_listener;
+
+ file_transfers = new Gee.HashMap >();
+ }
+
+ ~ToxAdapterFiletransferListenerImpl() {
+ logger.d("ToxAdapterFiletransferListenerImpl destroyed.");
+ }
+
+ public virtual void attach_to_session(ToxSession session) {
+ this.session = session;
+ session.set_filetransfer_listener(this);
+ friends = session.get_friends();
+ }
+
+ public virtual void start_transfer(FileTransfer transfer) throws Error {
+ logger.d("start_transfer");
+ session.file_control(transfer.get_friend_number(), transfer.get_file_number(), ToxCore.FileControl.RESUME);
+ transfer.set_state(FileTransferState.RUNNING);
+ }
+
+ public virtual void stop_transfer(FileTransfer transfer) throws Error {
+ logger.d("stop_transfer");
+ session.file_control(transfer.get_friend_number(), transfer.get_file_number(), ToxCore.FileControl.CANCEL);
+ transfer.set_state(FileTransferState.CANCEL);
+ unset_file_transfer(transfer.get_friend_number(), transfer.get_file_number());
+ }
+
+ public virtual void pause_transfer(FileTransfer transfer) throws Error {
+ logger.d("pause_transfer");
+ session.file_control(transfer.get_friend_number(), transfer.get_file_number(), ToxCore.FileControl.PAUSE);
+ transfer.set_state(FileTransferState.PAUSED);
+ }
+
+ public virtual void remove_transfer(FileTransfer transfer) throws Error {
+ var friend_number = transfer.get_friend_number();
+ var file_number = transfer.get_file_number();
+ var state = transfer.get_state();
+ logger.d(@"remove_transfer $friend_number:$file_number/%s".printf(state.to_string()));
+ try {
+ if (state != FileTransferState.CANCEL && state != FileTransferState.FINISHED) {
+ session.file_control(friend_number, file_number, ToxCore.FileControl.CANCEL);
+ }
+ } finally {
+ unset_file_transfer(friend_number, file_number);
+ transfers.remove(transfer);
+ conversations.get(friends.get(friend_number)).remove(transfer);
+ }
+ }
+
+ public virtual IContact get_contact_from_transfer(FileTransfer transfer) throws Error {
+ var contact = friends.@get(transfer.get_friend_number());
+ if (contact == null) {
+ throw new ToxError.GENERIC("Contact not found");
+ }
+ return contact;
+ }
+
+ public virtual void on_start_filetransfer(IContact contact, File file) throws Error {
+ logger.d("on_start_filetransfer");
+ var c = contact as Contact;
+ session.file_send_data(c.tox_friend_number, file);
+ }
+
+ public virtual void on_file_chunk_request(uint32 friend_number, uint32 file_number, uint64 position, uint64 length) {
+ logger.d("on_file_chunk_request");
+ var file_transfer = get_file_transfer(friend_number, file_number);
+ if (file_transfer == null) {
+ logger.e("Received file chunk request, but filetransfer does not exist.");
+ return;
+ }
+ var state = file_transfer.get_state();
+ if (state != FileTransferState.RUNNING && state != FileTransferState.PAUSED) {
+ logger.e("Received file chunk request, but filetransfer is not running/paused.");
+ return;
+ }
+ if (length <= 0) {
+ file_transfer.set_state(FileTransferState.FINISHED);
+ unset_file_transfer(friend_number, file_number);
+ return;
+ }
+ try {
+ var buf = file_transfer.read_data(length);
+ session.file_send_chunk(friend_number, file_number, position, buf);
+ } catch (Error e) {
+ logger.e("Reading data from file failed: " + e.message);
+ file_transfer.set_state(FileTransferState.FAILED);
+ return;
+ }
+ }
+
+ public virtual void on_file_send_avatar_received(uint32 friend_number, uint32 file_number, uint8[] avatar_data) {
+ logger.d("on_file_send_avatar_received");
+ var transfer = new FileTransferImpl.AvatarOutgoing(FileTransferDirection.OUTGOING, friend_number, file_number, avatar_data);
+ set_file_transfer(friend_number, file_number, transfer);
+ }
+
+ public virtual void on_file_send_data_received(uint32 friend_number, uint32 file_number, uint64 file_size, string file_name, GLib.File file) {
+ logger.d("on_file_send_data_received");
+ try {
+ var transfer = new FileTransferImpl.File(FileTransferDirection.OUTGOING, friend_number, file_number, file_size, file_name);
+ transfer.init_file(file);
+
+ set_file_transfer(friend_number, file_number, transfer);
+ transfers.append(transfer);
+ conversations.get(friends.get(friend_number)).append(transfer);
+ } catch (Error e) {
+ logger.e("file_control failed: " + e.message);
+ }
+ }
+
+ public virtual void on_file_recv_control(uint32 friend_number, uint32 file_number, ToxCore.FileControl control) {
+ logger.d("on_file_recv_control");
+ var file_transfer = get_file_transfer(friend_number, file_number);
+ if (file_transfer == null) {
+ logger.e("Received file control packet, but filetransfer does not exist");
+ return;
+ }
+ var state = file_transfer.get_state();
+ if (state != FileTransferState.INIT && state != FileTransferState.RUNNING && state != FileTransferState.PAUSED) {
+ logger.e("Received file control packet, but filetransfer is not paused/running");
+ return;
+ }
+ switch (control) {
+ case ToxCore.FileControl.CANCEL:
+ file_transfer.set_state(FileTransferState.CANCEL);
+ unset_file_transfer(friend_number, file_number);
+ break;
+ case ToxCore.FileControl.PAUSE:
+ file_transfer.set_state(FileTransferState.PAUSED);
+ break;
+ case ToxCore.FileControl.RESUME:
+ file_transfer.set_state(FileTransferState.RUNNING);
+ break;
+ }
+ }
+
+ private string create_auto_path(string auto_location) {
+ if (auto_location != "" && GLib.File.new_for_path(auto_location).query_exists()) {
+ return auto_location;
+ }
+ return R.constants.downloads_dir;
+ }
+
+ private GLib.File create_auto_file(string path, string filename) throws Error {
+ if (filename.length < 1 || filename == ".") {
+ filename = "file";
+ }
+ var index = filename.index_of(".", 1);
+ var start = filename.substring(0, index);
+ var end = index > 0 ? filename.substring(index) : "";
+
+ for (var i = 0;; i++) {
+ var name = GLib.Path.build_filename(path, start + (i == 0 ? "" : @"_$i") + end);
+ var file = File.new_for_path(name);
+ if (!file.query_exists()) {
+ return file;
+ }
+ }
+ }
+
+ public virtual void on_file_recv_data(uint32 friend_number, uint32 file_number, uint64 file_size, string filename) {
+ logger.d("on_file_recv_data");
+
+ var contact = friends.@get(friend_number) as Contact;
+ try {
+ var transfer = new FileTransferImpl.File(FileTransferDirection.INCOMING, friend_number, file_number, file_size, filename);
+ set_file_transfer(friend_number, file_number, transfer);
+ transfers.append(transfer);
+ conversations.get(friends.get(friend_number)).append(transfer);
+ notification_listener.on_filetransfer(transfer, contact);
+
+ if (contact.auto_filetransfer) {
+ var path = create_auto_path(contact.auto_location);
+ transfer.init_file(create_auto_file(path, filename));
+ start_transfer(transfer);
+ }
+
+ } catch (Error e) {
+ logger.e("file_control failed: " + e.message);
+ return;
+ }
+ }
+
+ public virtual void on_file_recv_avatar(uint32 friend_number, uint32 file_number, uint64 file_size) {
+ logger.d(@"on_file_recv_avatar $friend_number:$file_number");
+ if (file_size > MAX_AVATAR_SIZE) {
+ logger.i("avatar > MAX_AVATAR_SIZE, dropping transfer request");
+ try {
+ session.file_control(friend_number, file_number, ToxCore.FileControl.CANCEL);
+ } catch (Error e) {
+ logger.e("dropping transfer request failed: " + e.message);
+ }
+ return;
+ }
+ try {
+ session.file_control(friend_number, file_number, ToxCore.FileControl.RESUME);
+ var transfer = new FileTransferImpl.Avatar(FileTransferDirection.INCOMING, friend_number, file_number, file_size);
+ transfer.set_state(FileTransferState.RUNNING);
+ set_file_transfer(friend_number, file_number, transfer);
+ } catch (Error e) {
+ logger.e("file_control failed: " + e.message);
+ return;
+ }
+ }
+
+ private FileTransfer ? get_file_transfer(uint32 friend_number, uint32 file_number) {
+ var friend_transfers = file_transfers.@get(friend_number);
+ if (friend_transfers == null) {
+ logger.e("on_file_recv_chunk no transfer found for contact");
+ return null;
+ }
+ return friend_transfers.@get(file_number);
+ }
+
+ private void set_file_transfer(uint32 friend_number, uint32 file_number, FileTransfer? transfer) {
+ var friend_transfers = init_friend_transfers(friend_number);
+ friend_transfers.@set(file_number, transfer);
+ }
+
+ private void unset_file_transfer(uint32 friend_number, uint32 file_number) {
+ var friend_transfers = file_transfers.@get(friend_number);
+ if (friend_transfers != null) {
+ friend_transfers.unset(file_number);
+ }
+ }
+
+ private Gee.Map init_friend_transfers(uint32 friend_number) {
+ var friend_transfers = file_transfers.@get(friend_number);
+ if (friend_transfers == null) {
+ friend_transfers = new Gee.HashMap();
+ file_transfers.@set(friend_number, friend_transfers);
+ }
+ return friend_transfers;
+ }
+
+ private void cancel_transfer(uint32 friend_number, uint32 file_number) {
+ try {
+ session.file_control(friend_number, file_number, ToxCore.FileControl.CANCEL);
+ } catch (Error e) {
+ logger.e("Could not cancel transfer: " + e.message);
+ }
+ }
+
+ public virtual void on_file_recv_chunk(uint32 friend_number, uint32 file_number, uint64 position, uint8[] data) {
+ var friend_transfers = file_transfers.@get(friend_number);
+ if (friend_transfers == null) {
+ logger.e("on_file_recv_chunk no transfer found for contact");
+ return;
+ }
+ var transfer = friend_transfers.@get(file_number);
+ if (transfer == null) {
+ logger.e("on_file_recv_chunk no transfer found for file number");
+ return;
+ }
+ if (data.length > 0) {
+ try {
+ transfer.write_data(data);
+ } catch (Error e) {
+ logger.e("Error writing data to disk: " + e.message);
+ transfer.set_state(FileTransferState.FAILED);
+ cancel_transfer(friend_number, file_number);
+ }
+ } else {
+ transfer.set_state(FileTransferState.FINISHED);
+ unset_file_transfer(transfer.get_friend_number(), transfer.get_file_number());
+ if (!transfer.is_avatar()) {
+ return;
+ }
+
+ var contact = friends.@get(friend_number) as Contact;
+ try {
+ var buf = transfer.get_avatar_buffer();
+ var directory = GLib.File.new_for_path(R.constants.avatars_folder());
+ if (!directory.query_exists()) {
+ directory.make_directory();
+ }
+
+ var id = contact.get_id();
+ var filepath = GLib.Path.build_filename(R.constants.avatars_folder(), @"$id.png");
+ var file = GLib.File.new_for_path(filepath);
+ if (buf == null) {
+ logger.d("Empty avatar received.");
+ if (file.query_exists()) {
+ file.@delete();
+ }
+ contact.tox_image = null;
+ contact.changed();
+ } else {
+ file.replace_contents(buf, null, false, FileCreateFlags.NONE, null);
+ var pixbuf_loader = new Gdk.PixbufLoader();
+ pixbuf_loader.write(buf);
+ pixbuf_loader.close();
+ contact.tox_image = pixbuf_loader.get_pixbuf();
+ contact.changed();
+ }
+ } catch (Error e) {
+ logger.e("set image failed: " + e.message);
+ }
+ }
+ }
+ }
+}
diff --git a/src/tox/ToxAdapterFriendListener.vala b/src/tox/ToxAdapterFriendListener.vala
new file mode 100644
index 0000000..fe574b4
--- /dev/null
+++ b/src/tox/ToxAdapterFriendListener.vala
@@ -0,0 +1,263 @@
+/*
+ * ToxAdapterFriendListener.vala
+ *
+ * Copyright (C) 2018 Venom authors and contributors
+ *
+ * This file is part of Venom.
+ *
+ * Venom is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Venom is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Venom. If not, see .
+ */
+
+namespace Venom {
+ public class ToxAdapterFriendListenerImpl : ToxAdapterFriendListener, AddContactWidgetListener, ConversationWidgetListener, FriendInfoWidgetListener, FriendRequestWidgetListener, GLib.Object {
+ private unowned ToxSession session;
+ private ILogger logger;
+ private ObservableList contacts;
+ private NotificationListener notification_listener;
+ private GLib.HashTable conversations;
+ private GLib.HashTable messages_waiting_for_rr;
+
+ private unowned GLib.HashTable friends;
+ private Gee.Map tox_friend_requests;
+ private ObservableList friend_requests;
+
+ private Gee.HashMap friend_avatar_hashes;
+
+ private UserInfo user_info;
+ private GLib.Bytes avatar_hash;
+
+ public bool show_typing { get; set; }
+
+ public ToxAdapterFriendListenerImpl(ILogger logger, UserInfo user_info, ObservableList contacts, ObservableList friend_requests, GLib.HashTable conversations, NotificationListener notification_listener) {
+ logger.d("ToxAdapterFriendListenerImpl created.");
+ this.logger = logger;
+ this.user_info = user_info;
+ this.contacts = contacts;
+ this.friend_requests = friend_requests;
+ this.conversations = conversations;
+ this.notification_listener = notification_listener;
+
+ messages_waiting_for_rr = new GLib.HashTable(null, null);
+ tox_friend_requests = new Gee.HashMap();
+
+ user_info.info_changed.connect(on_info_changed);
+ avatar_hash = user_info.avatar.hash;
+ }
+
+ private void on_info_changed() {
+ if (user_info.is_connected && avatar_hash.compare(user_info.avatar.hash) != 0) {
+ avatar_hash = user_info.avatar.hash;
+ start_avatar_distribution();
+ }
+ }
+
+ private void start_avatar_distribution() {
+ logger.i("start_avatar_distribution");
+ uint8[] avatar_data;
+ user_info.avatar.pixbuf.save_to_buffer(out avatar_data, "png");
+ var contacts = friends.get_values();
+ foreach (var contact in contacts) {
+ var c = contact as Contact;
+ if (c.is_connected()) {
+ session.file_send_avatar((c as Contact).tox_friend_number, avatar_data);
+ }
+ }
+ }
+
+ ~ToxAdapterFriendListenerImpl() {
+ logger.d("ToxAdapterFriendListenerImpl destroyed.");
+ }
+
+ public virtual void attach_to_session(ToxSession session) {
+ this.session = session;
+ session.set_friend_listener(this);
+
+ friends = session.get_friends();
+
+ try {
+ session.self_get_friend_list_foreach((friend_number, friend_key) => {
+ on_friend_added(friend_number, friend_key);
+ });
+ } catch (Error e) {
+ logger.f("Could not retrieve friend list: " + e.message);
+ }
+ }
+
+ public virtual void on_remove_friend(IContact c) throws Error {
+ var contact = c as Contact;
+ session.friend_delete(contact.tox_friend_number);
+ }
+
+ public virtual void on_send_friend_request(string address, string message) throws Error {
+ var bin_address = Tools.hexstring_to_bin(address);
+ session.friend_add(bin_address, message);
+ }
+
+ public virtual void on_accept_friend_request(string id) throws Error {
+ var friend_request = tox_friend_requests.@get(id);
+ var public_key = Tools.hexstring_to_bin(id);
+ session.friend_add_norequest(public_key);
+
+ friend_requests.remove(friend_request);
+ tox_friend_requests.unset(id);
+ }
+
+ public virtual void on_reject_friend_request(string id) throws Error {
+ var friend_request = tox_friend_requests.@get(id);
+
+ friend_requests.remove(friend_request);
+ tox_friend_requests.unset(id);
+ }
+
+ public virtual void on_send_message(IContact c, string message) throws Error {
+ var contact = c as Contact;
+ session.friend_send_message(contact.tox_friend_number, message);
+ }
+
+ public virtual void on_set_typing(IContact c, bool typing) throws Error {
+ if (!show_typing) {
+ return;
+ }
+ var contact = c as Contact;
+ session.self_set_typing(contact.tox_friend_number, typing);
+ }
+
+ public virtual void on_friend_message(uint32 friend_number, string message_str) {
+ logger.d("on_friend_message");
+ var contact = friends.@get(friend_number) as Contact;
+ var conversation = conversations.@get(contact);
+ var message = new Message.incoming(contact, message_str);
+ notification_listener.on_unread_message(message, contact);
+ contact.unread_messages++;
+ contact.changed();
+ conversation.append(message);
+ }
+
+ public virtual void on_friend_read_receipt(uint32 friend_number, uint32 message_id) {
+ var message = messages_waiting_for_rr.@get(message_id);
+ if (message != null) {
+ message.received = true;
+ messages_waiting_for_rr.remove(message_id);
+
+ message.message_changed();
+ } else {
+ logger.f("Got read receipt for unknown message.");
+ }
+ }
+
+ public virtual void on_friend_name_changed(uint32 friend_number, string name) {
+ var contact = friends.@get(friend_number) as Contact;
+ contact.name = name;
+ contact.changed();
+ }
+
+ public virtual void on_friend_status_message_changed(uint32 friend_number, string message) {
+ logger.d("on_friend_status_message_changed");
+ var contact = friends.@get(friend_number) as Contact;
+ contact.status_message = message;
+ contact.changed();
+ }
+
+ public virtual void on_friend_request(uint8[] public_key, string message) {
+ logger.d("on_friend_request");
+ var id = Tools.bin_to_hexstring(public_key);
+ var request = new FriendRequest(id, message);
+ friend_requests.append(request);
+ tox_friend_requests.@set(id, request);
+ }
+
+ public virtual void on_friend_status_changed(uint32 friend_number, UserStatus status) {
+ logger.d("on_friend_status_changed");
+ var contact = friends.@get(friend_number) as Contact;
+ contact.user_status = status;
+ contact.changed();
+ }
+
+ public virtual void on_friend_connection_status_changed(uint32 friend_number, bool is_connected) {
+ logger.d("on_friend_connection_status_changed");
+ var contact = friends.@get(friend_number) as Contact;
+ contact.connected = is_connected;
+ contact.last_seen = new DateTime.from_unix_local((int64) session.friend_get_last_online(friend_number));
+ contact.changed();
+
+ if (is_connected) {
+ uint8[] avatar_data;
+ user_info.avatar.pixbuf.save_to_buffer(out avatar_data, "png");
+ session.file_send_avatar(contact.tox_friend_number, avatar_data);
+ }
+ }
+
+ public virtual void on_friend_typing_status_changed(uint32 friend_number, bool is_typing) {
+ logger.d("on_friend_typing_status_changed");
+ var contact = friends.@get(friend_number) as Contact;
+ contact._is_typing = is_typing;
+ contact.changed();
+ }
+
+ public virtual void on_friend_added(uint32 friend_number, uint8[] public_key) {
+ logger.d("on_friend_added");
+ var str_id = Tools.bin_to_hexstring(public_key);
+ var contact = new Contact(friend_number, str_id);
+ try {
+ contact.name = session.friend_get_name(friend_number);
+ contact.status_message = session.friend_get_status_message(friend_number);
+ contact.last_seen = new DateTime.from_unix_local((int64) session.friend_get_last_online(friend_number));
+ } catch (ToxError e) {
+ logger.i("Restoring contact information failed");
+ }
+
+ if (!conversations.contains(contact)) {
+ var conversation = new ObservableList();
+ conversation.set_list(new GLib.List());
+ conversations.@set(contact, conversation);
+ }
+
+ var filepath = GLib.Path.build_filename(R.constants.avatars_folder(), @"$str_id.png");
+ var file = File.new_for_path(filepath);
+ if (file.query_exists()) {
+ uint8[] buf;
+ try {
+ file.load_contents(null, out buf, null);
+ var pixbuf_loader = new Gdk.PixbufLoader();
+ pixbuf_loader.write(buf);
+ pixbuf_loader.close();
+ contact.tox_image = pixbuf_loader.get_pixbuf();
+ } catch (Error e) {
+ logger.i("could not read avatar data: " + e.message);
+ }
+ }
+
+ friends.@set(friend_number, contact);
+ contacts.append(contact);
+ }
+
+ public virtual void on_friend_deleted(uint32 friend_number) {
+ logger.d("on_friend_deleted");
+ var contact = friends.@get(friend_number);
+ conversations.remove(contact);
+ friends.remove(friend_number);
+ contacts.remove(contact);
+ }
+
+ public virtual void on_friend_message_sent(uint32 friend_number, uint32 message_id, string message) {
+ logger.d("on_friend_message_sent");
+ var contact = friends.@get(friend_number);
+ var conversation = conversations.@get(contact);
+ var msg = new Message.outgoing(contact, message);
+ msg.message_id = message_id;
+ conversation.append(msg);
+ messages_waiting_for_rr.@set(message_id, msg);
+ }
+ }
+}
diff --git a/src/tox/ToxAdapterSelfListener.vala b/src/tox/ToxAdapterSelfListener.vala
new file mode 100644
index 0000000..aed5c4b
--- /dev/null
+++ b/src/tox/ToxAdapterSelfListener.vala
@@ -0,0 +1,129 @@
+/*
+ * ToxAdapterSelfListener.vala
+ *
+ * Copyright (C) 2018 Venom authors and contributors
+ *
+ * This file is part of Venom.
+ *
+ * Venom is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Venom is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Venom. If not, see .
+ */
+
+namespace Venom {
+ public class ToxAdapterSelfListenerImpl : ToxAdapterSelfListener, UserInfoViewListener, GLib.Object {
+ private unowned ToxSession session;
+ private ILogger logger;
+ private UserInfo user_info;
+ private GLib.File avatar_file;
+ private GLib.Cancellable avatar_cancellable;
+
+ public ToxAdapterSelfListenerImpl(ILogger logger, UserInfo user_info) {
+ logger.d("ToxAdapterSelfListenerImpl created.");
+ this.logger = logger;
+ this.user_info = user_info;
+ this.avatar_cancellable = new Cancellable();
+ }
+
+ ~ToxAdapterSelfListenerImpl() {
+ logger.d("ToxAdapterSelfListenerImpl destroyed.");
+ }
+
+ public virtual void attach_to_session(ToxSession session) {
+ this.session = session;
+ session.set_session_listener(this);
+
+ user_info.tox_id = Tools.bin_to_hexstring(session.self_get_address());
+
+ var public_key = Tools.bin_to_hexstring(session.self_get_public_key());
+ var avatar_file_path = GLib.Path.build_filename(R.constants.avatars_folder(), public_key + ".png");
+ avatar_file = GLib.File.new_for_path(avatar_file_path);
+
+ get_user_info();
+ }
+
+ public virtual void set_self_name(string name) throws GLib.Error {
+ session.self_set_user_name(name);
+ user_info.name = name;
+ user_info.info_changed();
+ }
+
+ public virtual void set_self_status_message(string status_message) throws GLib.Error {
+ session.self_set_status_message(status_message);
+ user_info.status_message = status_message;
+ user_info.info_changed();
+ }
+
+ public virtual void set_self_avatar(Gdk.Pixbuf pixbuf) throws GLib.Error {
+ logger.d("ToxAdapterSelfListenerImpl set_self_avatar");
+ avatar_cancellable.cancel();
+ avatar_cancellable.reset();
+ uint8[] buf;
+ pixbuf.save_to_buffer(out buf, "png");
+ var bytes = new Bytes(buf);
+ avatar_file.replace_contents_bytes_async.begin(bytes, null, false, GLib.FileCreateFlags.REPLACE_DESTINATION, avatar_cancellable);
+
+ user_info.avatar.set_from_data(logger, buf, pixbuf);
+ user_info.custom_avatar = true;
+ user_info.info_changed();
+ }
+
+ public virtual void reset_self_avatar() throws GLib.Error {
+ logger.d("ToxAdapterSelfListenerImpl reset_self_avatar");
+ avatar_cancellable.cancel();
+ avatar_cancellable.reset();
+ if (user_info.custom_avatar) {
+ if (avatar_file.query_exists()) {
+ avatar_file.delete_async.begin(GLib.Priority.DEFAULT, avatar_cancellable);
+ }
+
+ user_info.avatar.reset();
+ user_info.custom_avatar = false;
+ user_info.info_changed();
+ }
+ }
+
+ private async void load_avatar(Cancellable? cancellable = null) {
+ try {
+ uint8[] buf;
+ yield avatar_file.load_contents_async(cancellable, out buf, null);
+ user_info.avatar.set_from_data(logger, buf);
+ user_info.custom_avatar = true;
+ user_info.info_changed();
+ } catch (GLib.Error e) {
+ logger.e("Can not load avatar: " + e.message);
+ }
+ }
+
+ private void get_user_info() {
+ user_info.name = session.self_get_name();
+ user_info.status_message = session.self_get_status_message();
+ user_info.user_status = session.self_get_user_status();
+ if (avatar_file.query_exists()) {
+ load_avatar.begin(avatar_cancellable);
+ } else {
+ user_info.info_changed();
+ }
+ }
+
+ public void on_self_connection_status_changed(bool is_connected) {
+ user_info.is_connected = is_connected;
+ user_info.info_changed();
+ }
+
+ public void self_set_user_status(UserStatus status) {
+ session.self_set_user_status(status);
+ user_info.user_status = status;
+ user_info.info_changed();
+ }
+ }
+}
diff --git a/src/tox/ToxContact.vala b/src/tox/ToxContact.vala
new file mode 100644
index 0000000..7c2964e
--- /dev/null
+++ b/src/tox/ToxContact.vala
@@ -0,0 +1,95 @@
+/*
+ * ToxContact.vala
+ *
+ * Copyright (C) 2013-2018 Venom authors and contributors
+ *
+ * This file is part of Venom.
+ *
+ * Venom is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Venom is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Venom. If not, see .
+ */
+
+namespace Venom {
+ public class Contact : IContact, GLib.Object {
+ // Saved in toxs savefile
+ public string tox_id { get; set; }
+ public uint32 tox_friend_number { get; set; }
+ public string name { get; set; default = ""; }
+ public string status_message { get; set; default = ""; }
+ public DateTime last_seen { get; set; default = new DateTime.now_local(); }
+ public UserStatus user_status { get; set; default = UserStatus.NONE; }
+ // Saved in venoms savefile
+ public string note { get; set; default = ""; }
+ public string alias { get; set; default = ""; }
+ public bool is_blocked { get; set; default = false; }
+ public string group { get; set; default = ""; }
+ public bool auto_conference { get; set; default = false; }
+ public bool auto_filetransfer { get; set; default = false; }
+ public string auto_location { get; set; default = ""; }
+ // Not saved
+ public bool connected { get; set; default = false; }
+ public Gdk.Pixbuf ? tox_image { get; set; default = null; }
+ public int unread_messages { get; set; default = 0; }
+ public bool _is_typing { get; set; default = false; }
+ public bool _show_notifications { get; set; default = true; }
+
+ public Contact(uint32 friend_number, string id) {
+ tox_friend_number = friend_number;
+ tox_id = id;
+ }
+
+ public string get_id() {
+ return tox_id;
+ }
+
+ public string get_name_string() {
+ return alias != "" ? alias : (name != "" ? name : tox_id);
+ }
+
+ public string get_status_string() {
+ return status_message;
+ }
+
+ public UserStatus get_status() {
+ return user_status;
+ }
+
+ public bool is_connected() {
+ return connected;
+ }
+
+ public bool is_typing() {
+ return _is_typing;
+ }
+
+ public bool is_conference() {
+ return false;
+ }
+
+ public Gdk.Pixbuf get_image() {
+ return tox_image ?? pixbuf_from_resource(R.icons.default_contact, 128);
+ }
+
+ public bool get_requires_attention() {
+ return unread_messages > 0;
+ }
+
+ public void clear_attention() {
+ unread_messages = 0;
+ }
+
+ public bool show_notifications() {
+ return _show_notifications;
+ }
+ }
+}
diff --git a/src/tox/ToxSession.vala b/src/tox/ToxSession.vala
new file mode 100644
index 0000000..4510958
--- /dev/null
+++ b/src/tox/ToxSession.vala
@@ -0,0 +1,850 @@
+/*
+ * ToxSession.vala
+ *
+ * Copyright (C) 2013-2018 Venom authors and contributors
+ *
+ * This file is part of Venom.
+ *
+ * Venom is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Venom is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Venom. If not, see .
+ */
+
+using ToxCore;
+
+namespace Venom {
+ public errordomain ToxError {
+ GENERIC
+ }
+
+ public enum ConferenceType {
+ TEXT,
+ AV
+ }
+
+ public class ToxConferencePeer : GLib.Object {
+ public uint32 peer_number;
+ public string? peer_name;
+ public uint8[] ? peer_key;
+ public bool is_self;
+ public bool is_known;
+ public ToxConferencePeer(uint32 peer_number, string? peer_name, uint8[] ? peer_key, bool is_self, bool is_known) {
+ this.peer_number = peer_number;
+ this.peer_name = peer_name;
+ this.peer_key = peer_key;
+ this.is_self = is_self;
+ this.is_known = is_known;
+ }
+ }
+
+ public delegate void GetFriendListCallback(uint32 friend_number, uint8[] friend_key);
+
+ public interface ToxSession : GLib.Object {
+ public abstract void set_session_listener(ToxAdapterSelfListener listener);
+ public abstract void set_filetransfer_listener(ToxAdapterFiletransferListener listener);
+ public abstract void set_friend_listener(ToxAdapterFriendListener listener);
+ public abstract void set_conference_listener(ToxAdapterConferenceListener listener);
+
+ public abstract void self_set_user_name(string name);
+ public abstract void self_set_status_message(string status);
+ public abstract void self_set_typing(uint32 friend_number, bool typing) throws ToxError;
+ public abstract void self_set_user_status(UserStatus status);
+
+ public abstract string self_get_name();
+ public abstract string self_get_status_message();
+ public abstract UserStatus self_get_user_status();
+
+ public abstract uint8[] self_get_address();
+ public abstract uint8[] self_get_public_key();
+
+ public abstract void self_get_friend_list_foreach(GetFriendListCallback callback) throws ToxError;
+ public abstract void friend_add(uint8[] address, string message) throws ToxError;
+ public abstract void friend_add_norequest(uint8[] address) throws ToxError;
+ public abstract void friend_delete(uint32 friend_number) throws ToxError;
+
+ public abstract void friend_send_message(uint32 friend_number, string message) throws ToxError;
+
+ public abstract string friend_get_name(uint32 friend_number) throws ToxError;
+ public abstract string friend_get_status_message(uint32 friend_number) throws ToxError;
+ public abstract uint64 friend_get_last_online(uint32 friend_number) throws ToxError;
+
+ public abstract uint32 conference_new(string title) throws ToxError;
+ public abstract void conference_delete(uint32 conference_number) throws ToxError;
+ public abstract void conference_invite(uint32 friend_number, uint32 conference_number) throws ToxError;
+ public abstract void conference_join(uint32 friend_number, ConferenceType type, uint8[] cookie) throws ToxError;
+
+ public abstract void conference_send_message(uint32 conference_number, string message) throws ToxError;
+ public abstract void conference_set_title(uint32 conference_number, string title) throws ToxError;
+ public abstract string conference_get_title(uint32 conference_number) throws ToxError;
+
+ public abstract void file_control(uint32 friend_number, uint32 file_number, FileControl control) throws ToxError;
+ public abstract void file_send_data(uint32 friend_number, GLib.File file) throws ToxError;
+ public abstract void file_send_avatar(uint32 friend_number, uint8[] avatar_data) throws ToxError;
+ public abstract void file_send_chunk(uint32 friend_number, uint32 file_number, uint64 position, uint8[] data) throws ToxError;
+
+ public abstract unowned GLib.HashTable get_friends();
+ }
+
+ public interface ToxAdapterSelfListener : GLib.Object {
+ public abstract void on_self_connection_status_changed(bool is_connected);
+ }
+
+ public interface ToxAdapterFriendListener : GLib.Object {
+ public abstract void on_friend_status_changed(uint32 friend_number, UserStatus status);
+ public abstract void on_friend_connection_status_changed(uint32 friend_number, bool connected);
+ public abstract void on_friend_name_changed(uint32 friend_number, string name);
+ public abstract void on_friend_status_message_changed(uint32 friend_number, string message);
+ public abstract void on_friend_typing_status_changed(uint32 friend_number, bool is_typing);
+
+ public abstract void on_friend_request(uint8[] public_key, string message);
+ public abstract void on_friend_added(uint32 friend_number, uint8[] public_key);
+ public abstract void on_friend_deleted(uint32 friend_number);
+
+ public abstract void on_friend_message(uint32 friend_number, string message);
+ public abstract void on_friend_message_sent(uint32 friend_number, uint32 message_id, string message);
+ public abstract void on_friend_read_receipt(uint32 friend_number, uint32 message_id);
+ }
+
+ public interface ToxAdapterConferenceListener : GLib.Object {
+ public abstract void on_conference_new(uint32 conference_number, string title);
+ public abstract void on_conference_deleted(uint32 conference_number);
+ public abstract void on_conference_invite_received(uint32 friend_number, Venom.ConferenceType type, uint8[] cookie);
+
+ public abstract void on_conference_title_changed(uint32 conference_number, uint32 peer_number, string title);
+ public abstract void on_conference_peer_list_changed(uint32 conference_number, ToxConferencePeer[] peers);
+ public abstract void on_conference_peer_renamed(uint32 conference_number, ToxConferencePeer peer);
+
+ public abstract void on_conference_message(uint32 conference_number, uint32 peer_number, MessageType type, string message);
+ public abstract void on_conference_message_sent(uint32 conference_number, string message);
+ }
+
+ public interface ToxAdapterFiletransferListener : GLib.Object {
+ public abstract void on_file_recv_data(uint32 friend_number, uint32 file_number, uint64 file_size, string filename);
+ public abstract void on_file_recv_avatar(uint32 friend_number, uint32 file_number, uint64 file_size);
+
+ public abstract void on_file_recv_chunk(uint32 friend_number, uint32 file_number, uint64 position, uint8[] data);
+ public abstract void on_file_recv_control(uint32 friend_number, uint32 file_number, FileControl control);
+
+ public abstract void on_file_chunk_request(uint32 friend_number, uint32 file_number, uint64 position, uint64 length);
+ public abstract void on_file_send_data_received(uint32 friend_number, uint32 file_number, uint64 file_size, string file_name, GLib.File file);
+ public abstract void on_file_send_avatar_received(uint32 friend_number, uint32 file_number, uint8[] avatar_data);
+ }
+
+ public class ToxSessionImpl : GLib.Object, ToxSession {
+ public Tox handle;
+ public ToxAV.ToxAV handle_av;
+ private Mutex mutex;
+
+ private IDhtNodeDatabase dht_node_database;
+ private ISettingsDatabase settings_database;
+
+ private List dht_nodes = new List();
+ private ILogger logger;
+ private ToxSessionThread sessionThread;
+
+ private ToxAdapterSelfListener self_listener;
+ private ToxAdapterFriendListener friend_listener;
+ private ToxAdapterConferenceListener conference_listener;
+ private ToxAdapterFiletransferListener filetransfer_listener;
+ private ToxSessionIO iohandler;
+ private GLib.HashTable friends;
+
+ public ToxSessionImpl(ToxSessionIO iohandler, IDhtNodeDatabase node_database, ISettingsDatabase settings_database, ILogger logger) throws Error {
+ this.dht_node_database = node_database;
+ this.settings_database = settings_database;
+ this.logger = logger;
+ this.mutex = Mutex();
+ this.iohandler = iohandler;
+
+ var options_error = ToxCore.ErrOptionsNew.OK;
+ var options = new ToxCore.Options(out options_error);
+
+ options.log_callback = on_tox_message;
+ friends = new GLib.HashTable(null, null);
+
+ var savedata = iohandler.load_sessiondata();
+ if (savedata != null) {
+ options.savedata_type = SaveDataType.TOX_SAVE;
+ options.set_savedata_data(savedata);
+ }
+
+ if (settings_database.enable_proxy) {
+ init_proxy(options);
+ }
+
+ options.udp_enabled = settings_database.enable_udp;
+ options.ipv6_enabled = settings_database.enable_ipv6;
+ options.local_discovery_enabled = settings_database.enable_local_discovery;
+ options.hole_punching_enabled = settings_database.enable_hole_punching;
+
+ // create handle
+ var error = ToxCore.ErrNew.OK;
+ handle = new ToxCore.Tox(options, out error);
+ if (error == ErrNew.PROXY_BAD_HOST || error == ErrNew.PROXY_BAD_PORT || error == ErrNew.PROXY_NOT_FOUND) {
+ var message = "Proxy could not be used: " + error.to_string();
+ logger.f(message);
+ throw new ToxError.GENERIC(message);
+ } else if (error != ToxCore.ErrNew.OK) {
+ var message = "Could not create tox instance: " + error.to_string();
+ logger.f(message);
+ throw new ToxError.GENERIC(message);
+ }
+
+ var error_av = ToxAV.ErrNew.OK;
+ handle_av = new ToxAV.ToxAV(handle, out error_av);
+ if (error_av != ToxAV.ErrNew.OK) {
+ var message = "Could not create toxav instance: " + error_av.to_string();
+ logger.f(message);
+ throw new ToxError.GENERIC(message);
+ }
+
+ handle.callback_self_connection_status(on_self_connection_status_cb);
+ handle.callback_friend_connection_status(on_friend_connection_status_cb);
+ handle.callback_friend_message(on_friend_message_cb);
+ handle.callback_friend_name(on_friend_name_cb);
+ handle.callback_friend_status_message(on_friend_status_message_cb);
+ handle.callback_friend_status(on_friend_status_cb);
+ handle.callback_friend_read_receipt(on_friend_read_receipt_cb);
+ handle.callback_friend_request(on_friend_request_cb);
+ handle.callback_friend_typing(on_friend_typing_cb);
+
+ handle.callback_conference_title(on_conference_title_cb);
+ handle.callback_conference_invite(on_conference_invite_cb);
+ handle.callback_conference_message(on_conference_message_cb);
+ handle.callback_conference_peer_name(on_conference_peer_name_cb);
+ handle.callback_conference_peer_list_changed(on_conference_peer_list_changed_cb);
+
+ handle.callback_file_recv(on_file_recv_cb);
+ handle.callback_file_recv_chunk(on_file_recv_chunk_cb);
+ handle.callback_file_recv_control(on_file_recv_control_cb);
+ handle.callback_file_chunk_request(on_file_chunk_request_cb);
+
+ init_dht_nodes();
+ sessionThread = new ToxSessionThreadImpl(this, logger, dht_nodes);
+ sessionThread.start();
+ logger.d("ToxSession created.");
+ }
+
+ // destructor
+ ~ToxSessionImpl() {
+ logger.i("ToxSession stopping background thread.");
+ sessionThread.stop();
+ logger.i("ToxSession saving session data.");
+ iohandler.save_sessiondata(handle.get_savedata());
+ handle = null;
+ handle_av = null;
+ logger.d("ToxSession destroyed.");
+ }
+
+ private void init_proxy(ToxCore.Options options) {
+ if (settings_database.enable_custom_proxy) {
+ options.proxy_type = ProxyType.SOCKS5;
+ options.proxy_host = settings_database.custom_proxy_host;
+ options.proxy_port = (uint16) settings_database.custom_proxy_port;
+ logger.i("Using custom socks5 proxy: socks5://%s:%u.".printf(options.proxy_host, options.proxy_port));
+ return;
+ } else {
+ string[] proxy_strings = {};
+ ProxyResolver proxy_resolver = ProxyResolver.get_default();
+ try {
+ proxy_strings = proxy_resolver.lookup("socks://tox.im");
+ } catch (Error e) {
+ logger.e("Error when looking up proxy settings: " + e.message);
+ return;
+ }
+
+ Regex proxy_regex = null;
+ try {
+ proxy_regex = new GLib.Regex("^(?Psocks5)://((?P[^:]*)(:(?P.*))?@)?(?P.*):(?P.*)");
+ } catch (GLib.Error e) {
+ logger.f("Error creating tox uri regex: " + e.message);
+ return;
+ }
+
+ foreach (var proxy in proxy_strings) {
+ if (proxy.has_prefix("socks5:")) {
+ GLib.MatchInfo info = null;
+ if (proxy_regex != null && proxy_regex.match(proxy, 0, out info)) {
+ options.proxy_type = ProxyType.SOCKS5;
+ options.proxy_host = info.fetch_named("host");
+ options.proxy_port = (uint16) int.parse(info.fetch_named("port"));
+ logger.i("Using socks5 proxy found in system settings: socks5://%s:%u.".printf(options.proxy_host, options.proxy_port));
+ return;
+ } else {
+ logger.i("socks5 proxy does not match regex: " + proxy);
+ }
+ }
+ }
+
+ logger.i("No usable proxy found in system settings, connecting directly.");
+ }
+ }
+
+ private void init_dht_nodes() {
+ var nodeFactory = new DhtNodeFactory();
+ dht_nodes = dht_node_database.getDhtNodes(nodeFactory);
+ logger.d("Items in dht node list: %u".printf(dht_nodes.length()));
+ if (dht_nodes.length() == 0) {
+ logger.d("Node database empty, populating from static database.");
+ var nodeDatabase = new JsonWebDhtNodeDatabase(logger);
+ var nodes = nodeDatabase.getDhtNodes(nodeFactory);
+ foreach (var node in nodes) {
+ dht_node_database.insertDhtNode(node.pub_key, node.host, node.port, node.is_blocked, node.maintainer, node.location);
+ }
+ dht_nodes = dht_node_database.getDhtNodes(nodeFactory);
+ if (dht_nodes.length() == 0) {
+ logger.e("Node initialisation from static database failed.");
+ }
+ }
+ }
+
+ public virtual unowned GLib.HashTable get_friends() {
+ return friends;
+ }
+
+ public void on_tox_message(Tox self, ToxCore.LogLevel level, string file, uint32 line, string func, string message) {
+ var tag = TermColor.YELLOW + "TOX" + TermColor.RESET;
+ var msg = @"[$tag] $message ($func $file:$line)";
+ switch (level) {
+ case ToxCore.LogLevel.TRACE:
+ case ToxCore.LogLevel.DEBUG:
+ logger.d(msg);
+ break;
+ case ToxCore.LogLevel.INFO:
+ logger.i(msg);
+ break;
+ case ToxCore.LogLevel.WARNING:
+ logger.w(msg);
+ break;
+ case ToxCore.LogLevel.ERROR:
+ logger.e(msg);
+ break;
+ }
+ }
+
+ public virtual void set_session_listener(ToxAdapterSelfListener listener) {
+ this.self_listener = listener;
+ }
+
+ public virtual void set_filetransfer_listener(ToxAdapterFiletransferListener listener) {
+ this.filetransfer_listener = listener;
+ }
+
+ public virtual void set_friend_listener(ToxAdapterFriendListener listener) {
+ this.friend_listener = listener;
+ }
+
+ public virtual void set_conference_listener(ToxAdapterConferenceListener listener) {
+ this.conference_listener = listener;
+ }
+
+ private static string copy_data_string(uint8[] data) {
+ var t = new uint8[data.length + 1];
+ Memory.copy(t, data, data.length);
+ return (string) t;
+ }
+
+ private static uint8[] copy_data(uint8[] data, uint len) {
+ var t = new uint8[len];
+ Memory.copy(t, data, len);
+ return t;
+ }
+
+ private static void on_self_connection_status_cb(Tox self, Connection connection_status, void* user_data) {
+ var session = (ToxSessionImpl) user_data;
+ session.logger.d("on_self_connection_status_cb");
+ var user_status = from_connection(connection_status);
+ Idle.add(() => { session.self_listener.on_self_connection_status_changed(user_status); return false; });
+ }
+
+ private static void on_friend_connection_status_cb(Tox self, uint32 friend_number, Connection connection_status, void* user_data) {
+ var session = (ToxSessionImpl) user_data;
+ session.logger.d("on_friend_connection_status_cb");
+ var user_status = from_connection(connection_status);
+ Idle.add(() => { session.friend_listener.on_friend_connection_status_changed(friend_number, user_status); return false; });
+ }
+
+ private static void on_friend_name_cb(Tox self, uint32 friend_number, uint8[] name, void* user_data) {
+ var session = (ToxSessionImpl) user_data;
+ session.logger.d("on_friend_name_cb");
+ var name_str = copy_data_string(name);
+ Idle.add(() => { session.friend_listener.on_friend_name_changed(friend_number, name_str); return false; });
+ }
+
+ private static void on_friend_request_cb(Tox self, uint8[] key, uint8[] message, void* user_data) {
+ var session = (ToxSessionImpl) user_data;
+ session.logger.d("on_friend_request_cb");
+ var key_copy = copy_data(key, public_key_size());
+ var message_str = copy_data_string(message);
+ Idle.add(() => { session.friend_listener.on_friend_request(key_copy, message_str); return false; });
+ }
+
+ private static void on_friend_message_cb(Tox self, uint32 friend_number, MessageType type, uint8[] message, void* user_data) {
+ var session = (ToxSessionImpl) user_data;
+ session.logger.d("on_friend_message_cb");
+ var message_str = copy_data_string(message);
+ Idle.add(() => { session.friend_listener.on_friend_message(friend_number, message_str); return false; });
+ }
+
+ private static void on_friend_status_message_cb(Tox self, uint32 friend_number, uint8[] message, void* user_data) {
+ var session = (ToxSessionImpl) user_data;
+ session.logger.d("on_friend_status_message_cb");
+ var message_str = copy_data_string(message);
+ Idle.add(() => { session.friend_listener.on_friend_status_message_changed(friend_number, message_str); return false; });
+ }
+
+ private static void on_friend_status_cb(Tox self, uint32 friend_number, ToxCore.UserStatus status, void* user_data) {
+ var session = (ToxSessionImpl) user_data;
+ session.logger.d("on_friend_status_cb");
+ var user_status = from_user_status(status);
+ Idle.add(() => { session.friend_listener.on_friend_status_changed(friend_number, user_status); return false; });
+ }
+
+ private static void on_friend_typing_cb(Tox self, uint32 friend_number, bool is_typing, void* user_data) {
+ var session = (ToxSessionImpl) user_data;
+ session.logger.d("on_friend_typing_cb");
+ Idle.add(() => { session.friend_listener.on_friend_typing_status_changed(friend_number, is_typing); return false; });
+ }
+
+ private static void on_friend_read_receipt_cb(Tox self, uint32 friend_number, uint32 message_id, void* user_data) {
+ var session = (ToxSessionImpl) user_data;
+ session.logger.d("on_friend_read_receipt_cb");
+
+ Idle.add(() => { session.friend_listener.on_friend_read_receipt(friend_number, message_id); return false; });
+ }
+
+ private static void on_conference_title_cb(Tox self, uint32 conference_number, uint32 peer_number, uint8[] title, void *user_data) {
+ var session = (ToxSessionImpl) user_data;
+ session.logger.d("on_conference_title_cb");
+
+ var title_str = copy_data_string(title);
+ Idle.add(() => { session.conference_listener.on_conference_title_changed(conference_number, peer_number, title_str); return false; });
+ }
+
+ private static void on_conference_invite_cb(Tox self, uint32 friend_number, ToxCore.ConferenceType type, uint8[] cookie, void *user_data) {
+ var session = (ToxSessionImpl) user_data;
+ session.logger.d("on_conference_invite_cb type:" + type.to_string());
+ var gc_type = (type == ToxCore.ConferenceType.AV) ? ConferenceType.AV : ConferenceType.TEXT;
+ var cookie_copy = copy_data(cookie, cookie.length);
+ Idle.add(() => { session.conference_listener.on_conference_invite_received(friend_number, gc_type, cookie_copy); return false; });
+ }
+
+ private void on_av_conference_audio_frame() {
+
+ }
+
+ private static void on_conference_message_cb(Tox self, uint32 conference_number, uint32 peer_number, MessageType type, uint8[] message, void *user_data) {
+ var session = (ToxSessionImpl) user_data;
+ session.logger.d("on_conference_message_cb");
+ var message_str = copy_data_string(message);
+ var err = ErrConferencePeerQuery.OK;
+ var is_ours = self.conference_peer_number_is_ours(conference_number, peer_number, out err);
+ if (err != ErrConferencePeerQuery.OK) {
+ session.logger.e("conference_peer_number_is_ours failed: " + err.to_string());
+ return;
+ }
+ if (is_ours) {
+ Idle.add(() => { session.conference_listener.on_conference_message_sent(conference_number, message_str); return false; });
+ } else {
+ Idle.add(() => { session.conference_listener.on_conference_message(conference_number, peer_number, type, message_str); return false; });
+ }
+ }
+
+ private static void on_conference_peer_name_cb(Tox self, uint32 conference_number, uint32 peer_number, uint8[] name, void* user_data) {
+ var session = (ToxSessionImpl) user_data;
+ session.logger.d("on_conference_peer_name_cb");
+ var peer_name = copy_data_string(name);
+ var err = ErrConferencePeerQuery.OK;
+ var peer_public_key = self.conference_peer_get_public_key(conference_number, peer_number, out err);
+ if (err != ErrConferencePeerQuery.OK) {
+ session.logger.e("conference_peer_get_public_key failed: " + err.to_string());
+ return;
+ }
+ var is_self = self.conference_peer_number_is_ours(conference_number, peer_number, out err);
+ var is_known = false;
+ if (!is_self) {
+ var err_pubkey = ErrFriendByPublicKey.OK;
+ self.friend_by_public_key(peer_public_key, out err_pubkey);
+ is_known = err_pubkey == ErrFriendByPublicKey.OK;
+ }
+ var peer = new ToxConferencePeer(peer_number, peer_name, peer_public_key, is_self, is_known);
+ Idle.add(() => { session.conference_listener.on_conference_peer_renamed(conference_number, peer); return false; });
+ }
+
+ private static void on_conference_peer_list_changed_cb(Tox self, uint32 conference_number, void* user_data) {
+ var session = (ToxSessionImpl) user_data;
+ session.logger.d("on_conference_peer_list_changed_cb");
+ var err = ErrConferencePeerQuery.OK;
+ var peer_count = self.conference_peer_count(conference_number, out err);
+ if (err != ErrConferencePeerQuery.OK) {
+ session.logger.e(@"Could not query peer count for conference $conference_number: " + err.to_string());
+ return;
+ }
+ var peers = new ToxConferencePeer[peer_count];
+ for (var i = 0; i < peer_count; i++) {
+ var peer_public_key = self.conference_peer_get_public_key(conference_number, i, out err);
+ var peer_name = self.conference_peer_get_name(conference_number, i, out err);
+ var is_self = self.conference_peer_number_is_ours(conference_number, i, out err);
+ var err_pubkey = ErrFriendByPublicKey.OK;
+ self.friend_by_public_key(peer_public_key, out err_pubkey);
+ var is_known = err_pubkey == ErrFriendByPublicKey.OK;
+ peers[i] = new ToxConferencePeer(i, peer_name, peer_public_key, is_self, is_known);
+ }
+ Idle.add(() => { session.conference_listener.on_conference_peer_list_changed(conference_number, peers); return false; });
+ }
+
+ private static void on_file_recv_cb(Tox self, uint32 friend_number, uint32 file_number, uint32 kind, uint64 file_size, uint8[] filename, void *user_data) {
+ var session = (ToxSessionImpl) user_data;
+ var kind_type = (FileKind) kind;
+ var kiB = file_size / 1024f;
+ var filename_str = copy_data_string(filename);
+ var kind_type_str = kind_type.to_string();
+ session.logger.d(@"on_file_recv_cb: $friend_number:$file_number ($kind_type_str) $kiB kiB");
+ switch (kind_type) {
+ case FileKind.DATA:
+ Idle.add(() => { session.filetransfer_listener.on_file_recv_data(friend_number, file_number, file_size, filename_str); return false; });
+ break;
+ case FileKind.AVATAR:
+ Idle.add(() => { session.filetransfer_listener.on_file_recv_avatar(friend_number, file_number, file_size); return false; });
+ break;
+ }
+ }
+
+ private static void on_file_recv_chunk_cb(Tox self, uint32 friend_number, uint32 file_number, uint64 position, uint8[] data, void* user_data) {
+ var session = (ToxSessionImpl) user_data;
+ session.logger.d(@"on_file_recv_chunk_cb: $friend_number:$file_number $position");
+ var data_copy = copy_data(data, data.length);
+ Idle.add(() => { session.filetransfer_listener.on_file_recv_chunk(friend_number, file_number, position, data_copy); return false; });
+ }
+
+ private static void on_file_recv_control_cb(Tox self, uint32 friend_number, uint32 file_number, FileControl control, void* user_data) {
+ var session = (ToxSessionImpl) user_data;
+ var control_str = control.to_string();
+ session.logger.d(@"on_file_recv_control_cb: $friend_number:$file_number $control_str");
+ Idle.add(() => { session.filetransfer_listener.on_file_recv_control(friend_number, file_number, control); return false; });
+ }
+
+ private static void on_file_chunk_request_cb(Tox self, uint32 friend_number, uint32 file_number, uint64 position, size_t length, void* user_data) {
+ var session = (ToxSessionImpl) user_data;
+ session.logger.d(@"on_file_chunk_request_cb: $friend_number:$file_number $position $length");
+ Idle.add(() => { session.filetransfer_listener.on_file_chunk_request(friend_number, file_number, position, length); return false; });
+ }
+
+ private static bool from_connection(Connection connection_status) {
+ return connection_status != Connection.NONE;
+ }
+
+ private static Venom.UserStatus from_user_status(ToxCore.UserStatus user_status) {
+ switch (user_status) {
+ case ToxCore.UserStatus.NONE:
+ return Venom.UserStatus.NONE;
+ case ToxCore.UserStatus.AWAY:
+ return Venom.UserStatus.AWAY;
+ case ToxCore.UserStatus.BUSY:
+ return Venom.UserStatus.BUSY;
+ }
+ assert_not_reached();
+ }
+
+ public virtual string self_get_name() {
+ return handle.self_get_name();
+ }
+
+ public virtual string self_get_status_message() {
+ return handle.self_get_status_message();
+ }
+
+ public virtual void self_get_friend_list_foreach(GetFriendListCallback callback) throws ToxError {
+ var friend_numbers = handle.self_get_friend_list();
+ for (var i = 0; i < friend_numbers.length; i++) {
+ var friend_number = friend_numbers[i];
+ var friend_key = friend_get_public_key(friend_number);
+ callback(friend_number, friend_key);
+ }
+ }
+
+ public virtual void self_set_user_name(string name) {
+ var e = ErrSetInfo.OK;
+ if (!handle.self_set_name(name, out e)) {
+ logger.e("set_user_name failed: " + e.to_string());
+ }
+ }
+
+ public virtual uint8[] self_get_address() {
+ return handle.self_get_address();
+ }
+
+ public virtual uint8[] self_get_public_key() {
+ return handle.self_get_public_key();
+ }
+
+ public virtual void self_set_status_message(string status) {
+ var e = ErrSetInfo.OK;
+ if (!handle.self_set_status_message(status, out e)) {
+ logger.e("set_user_status failed: " + e.to_string());
+ }
+ }
+
+ public void self_set_user_status(UserStatus status) {
+ switch (status) {
+ case UserStatus.AWAY:
+ handle.self_status = ToxCore.UserStatus.AWAY;
+ break;
+ case UserStatus.BUSY:
+ handle.self_status = ToxCore.UserStatus.BUSY;
+ break;
+ default:
+ handle.self_status = ToxCore.UserStatus.NONE;
+ break;
+ }
+ }
+
+ public UserStatus self_get_user_status() {
+ return from_user_status(handle.self_status);
+ }
+
+ public virtual uint8[] friend_get_public_key(uint32 friend_number) throws ToxError {
+ var e = ErrFriendGetPublicKey.OK;
+ var ret = handle.friend_get_public_key(friend_number, out e);
+ if (e != ErrFriendGetPublicKey.OK) {
+ logger.e("friend_get_public_key failed: " + e.to_string());
+ throw new ToxError.GENERIC(e.to_string());
+ }
+ return ret;
+ }
+
+ public virtual string friend_get_name(uint32 friend_number) throws ToxError {
+ var e = ErrFriendQuery.OK;
+ var ret = handle.friend_get_name(friend_number, out e);
+ if (e != ErrFriendQuery.OK) {
+ logger.e("friend_get_name failed: " + e.to_string());
+ throw new ToxError.GENERIC(e.to_string());
+ }
+ return ret;
+ }
+
+ public virtual string friend_get_status_message(uint32 friend_number) throws ToxError {
+ var e = ErrFriendQuery.OK;
+ var ret = handle.friend_get_status_message(friend_number, out e);
+ if (e != ErrFriendQuery.OK) {
+ logger.e("friend_get_status_message failed: " + e.to_string());
+ throw new ToxError.GENERIC(e.to_string());
+ }
+ return ret;
+ }
+
+ public virtual uint64 friend_get_last_online(uint32 friend_number) throws ToxError {
+ var e = ErrFriendGetLastOnline.OK;
+ var ret = handle.friend_get_last_online(friend_number, out e);
+ if (e != ErrFriendGetLastOnline.OK) {
+ logger.e("friend_get_last_online failed: " + e.to_string());
+ throw new ToxError.GENERIC(e.to_string());
+ }
+ return ret;
+ }
+
+ public virtual void friend_add(uint8[] address, string message) throws ToxError {
+ if (address.length != address_size()) {
+ throw new ToxError.GENERIC(_("Address must consist of 76 hexadecimal characters"));
+ }
+ var e = ErrFriendAdd.OK;
+ var friend_number = handle.friend_add(address, message, out e);
+ if (e != ErrFriendAdd.OK) {
+ logger.i("friend_add failed: " + e.to_string());
+ throw new ToxError.GENERIC(e.to_string());
+ }
+ var key = friend_get_public_key(friend_number);
+ friend_listener.on_friend_added(friend_number, key);
+ }
+
+ public virtual void friend_add_norequest(uint8[] public_key) throws ToxError {
+ var e = ErrFriendAdd.OK;
+ var friend_number = handle.friend_add_norequest(public_key, out e);
+ if (e != ErrFriendAdd.OK) {
+ logger.i("friend_add failed: " + e.to_string());
+ throw new ToxError.GENERIC(e.to_string());
+ }
+ friend_listener.on_friend_added(friend_number, public_key);
+ }
+
+ public virtual void friend_delete(uint32 friend_number) throws ToxError {
+ var e = ErrFriendDelete.OK;
+ if (!handle.friend_delete(friend_number, out e)) {
+ logger.i("friend_delete failed: " + e.to_string());
+ throw new ToxError.GENERIC(e.to_string());
+ }
+ friend_listener.on_friend_deleted(friend_number);
+ }
+
+ public virtual void friend_send_message(uint32 friend_number, string message) throws ToxError {
+ var e = ErrFriendSendMessage.OK;
+ var ret = handle.friend_send_message(friend_number, MessageType.NORMAL, message, out e);
+ if (e != ErrFriendSendMessage.OK) {
+ logger.i("friend_send_message failed: " + e.to_string());
+ throw new ToxError.GENERIC(e.to_string());
+ }
+ friend_listener.on_friend_message_sent(friend_number, ret, message);
+ }
+
+ public virtual void self_set_typing(uint32 friend_number, bool typing) throws ToxError {
+ var e = ErrSetTyping.OK;
+ handle.self_set_typing(friend_number, typing, out e);
+ if (e != ErrSetTyping.OK) {
+ logger.i("self_set_typing failed: " + e.to_string());
+ throw new ToxError.GENERIC(e.to_string());
+ }
+ }
+
+ public virtual void file_control(uint32 friend_number, uint32 file_number, FileControl control) throws ToxError {
+ var e = ErrFileControl.OK;
+ handle.file_control(friend_number, file_number, control, out e);
+ if (e != ErrFileControl.OK) {
+ throw new ToxError.GENERIC(e.to_string());
+ }
+ }
+
+ public virtual void file_send_avatar(uint32 friend_number, uint8[] avatar_data) throws ToxError {
+ var e = ErrFileSend.OK;
+ var ret = handle.file_send(friend_number, FileKind.AVATAR, avatar_data.length, null, "", out e);
+ if (e != ErrFileSend.OK) {
+ logger.e("file send avatar request failed: " + e.to_string());
+ throw new ToxError.GENERIC(e.to_string());
+ }
+ filetransfer_listener.on_file_send_avatar_received(friend_number, ret, avatar_data);
+ }
+
+ public virtual void file_send_data(uint32 friend_number, GLib.File file) throws ToxError {
+ uint64 file_size = Tools.get_file_size(file);
+ var file_name = file.get_basename();
+
+ var e = ErrFileSend.OK;
+ var ret = handle.file_send(friend_number, FileKind.DATA, file_size, null, file_name, out e);
+ if (e != ErrFileSend.OK) {
+ logger.e("file send request failed: " + e.to_string());
+ throw new ToxError.GENERIC(e.to_string());
+ }
+ filetransfer_listener.on_file_send_data_received(friend_number, ret, file_size, file_name, file);
+ }
+
+ public virtual void file_send_chunk(uint32 friend_number, uint32 file_number, uint64 position, uint8[] data) throws ToxError {
+ var e = ErrFileSendChunk.OK;
+ handle.file_send_chunk(friend_number, file_number, position, data, out e);
+ if (e != ErrFileSendChunk.OK) {
+ logger.e("sending chunk failed: " + e.to_string());
+ throw new ToxError.GENERIC(e.to_string());
+ }
+ }
+
+ private void conference_set_title_private(uint32 conference_number, string title) throws ToxError {
+ var e = ErrConferenceTitle.OK;
+ handle.conference_set_title(conference_number, title, out e);
+ if (e != ErrConferenceTitle.OK) {
+ logger.e("setting conference title failed: " + e.to_string());
+ throw new ToxError.GENERIC(e.to_string());
+ }
+ }
+
+ public virtual void conference_set_title(uint32 conference_number, string title) throws ToxError {
+ conference_set_title_private(conference_number, title);
+ conference_listener.on_conference_title_changed(conference_number, 0, title);
+ }
+
+ public virtual string conference_get_title(uint32 conference_number) throws ToxError {
+ var e = ErrConferenceTitle.OK;
+ var title = handle.conference_get_title(conference_number, out e);
+ if (e != ErrConferenceTitle.OK) {
+ logger.e("getting conference title failed: " + e.to_string());
+ throw new ToxError.GENERIC(e.to_string());
+ }
+ return title;
+ }
+
+ public virtual uint32 conference_new(string title) throws ToxError {
+ var e = ErrConferenceNew.OK;
+ var conference_number = handle.conference_new(out e);
+ if (e != ErrConferenceNew.OK) {
+ logger.e("creating conference failed: " + e.to_string());
+ throw new ToxError.GENERIC(e.to_string());
+ }
+ if (title != "") {
+ try {
+ conference_set_title_private(conference_number, title);
+ } catch (ToxError e) {
+ var err_conference_delete = ErrConferenceDelete.OK;
+ handle.conference_delete(conference_number, out err_conference_delete);
+ throw e;
+ }
+ }
+ conference_listener.on_conference_new(conference_number, title);
+ return conference_number;
+ }
+
+ public virtual void conference_join(uint32 friend_number, ConferenceType type, uint8[] cookie) throws ToxError {
+ uint32 conference_number;
+ switch (type) {
+ case ConferenceType.AV:
+ conference_number = ToxAV.ToxAV.join_av_groupchat(handle, friend_number, cookie, on_av_conference_audio_frame);
+ if (conference_number < 0) {
+ var message = @"Conference AV join failed: $conference_number";
+ logger.e(message);
+ throw new ToxError.GENERIC(message);
+ }
+ break;
+ default:
+ var err = ErrConferenceJoin.OK;
+ conference_number = handle.conference_join(friend_number, cookie, out err);
+ if (err != ErrConferenceJoin.OK) {
+ logger.e("Conference join failed: " + err.to_string());
+ throw new ToxError.GENERIC(err.to_string());
+ }
+ break;
+ }
+
+ conference_listener.on_conference_new(conference_number, "");
+ }
+
+ public virtual void conference_delete(uint32 conference_number) throws ToxError {
+ var e = ErrConferenceDelete.OK;
+ handle.conference_delete(conference_number, out e);
+ if (e != ErrConferenceDelete.OK) {
+ logger.e("deleting conference failed: " + e.to_string());
+ throw new ToxError.GENERIC(e.to_string());
+ }
+ conference_listener.on_conference_deleted(conference_number);
+ }
+
+ public virtual void conference_invite(uint32 friend_number, uint32 conference_number) throws ToxError {
+ var e = ErrConferenceInvite.OK;
+ handle.conference_invite(friend_number, conference_number, out e);
+ if (e != ErrConferenceInvite.OK) {
+ logger.e("Sending conference invite failed: " + e.to_string());
+ throw new ToxError.GENERIC(e.to_string());
+ }
+ }
+
+ public virtual void conference_send_message(uint32 conference_number, string message) throws ToxError {
+ var e = ErrConferenceSendMessage.OK;
+ handle.conference_send_message(conference_number, MessageType.NORMAL, message, out e);
+ if (e != ErrConferenceSendMessage.OK) {
+ logger.e("sending conference message failed: " + e.to_string());
+ throw new ToxError.GENERIC(e.to_string());
+ }
+ }
+
+ public void @lock() {
+ mutex.@lock();
+ }
+ public void unlock() {
+ mutex.unlock();
+ }
+ }
+}
diff --git a/src/tox/ToxSessionIO.vala b/src/tox/ToxSessionIO.vala
new file mode 100644
index 0000000..90430e4
--- /dev/null
+++ b/src/tox/ToxSessionIO.vala
@@ -0,0 +1,58 @@
+/*
+ * ToxSessionIO.vala
+ *
+ * Copyright (C) 2018 Venom authors and contributors
+ *
+ * This file is part of Venom.
+ *
+ * Venom is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Venom is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Venom. If not, see .
+ */
+
+namespace Venom {
+
+ public interface ToxSessionIO : GLib.Object {
+ public abstract uint8[] ? load_sessiondata();
+ public abstract void save_sessiondata(uint8[] sessiondata);
+ }
+
+ public class ToxSessionIOImpl : ToxSessionIO, GLib.Object {
+ private ILogger logger;
+
+ public ToxSessionIOImpl(ILogger logger) {
+ this.logger = logger;
+ }
+
+ public virtual uint8[] ? load_sessiondata() {
+ var file = File.new_for_path(R.constants.tox_data_filename());
+ uint8[] contents;
+ string etag_out;
+ try {
+ file.load_contents(null, out contents, out etag_out);
+ } catch (Error e) {
+ logger.i("could not read tox savefile: " + e.message);
+ return null;
+ }
+ return contents;
+ }
+
+ public virtual void save_sessiondata(uint8[] sessiondata) {
+ var file = File.new_for_path(R.constants.tox_data_filename());
+ try {
+ file.replace_contents(sessiondata, null, false, FileCreateFlags.NONE, null, null);
+ } catch (Error e) {
+ logger.f("Saving tox session data failed: " + e.message);
+ }
+ }
+ }
+}
diff --git a/src/tox/ToxSessionThread.vala b/src/tox/ToxSessionThread.vala
new file mode 100644
index 0000000..6435384
--- /dev/null
+++ b/src/tox/ToxSessionThread.vala
@@ -0,0 +1,120 @@
+/*
+ * ToxSessionThread.vala
+ *
+ * Copyright (C) 2018 Venom authors and contributors
+ *
+ * This file is part of Venom.
+ *
+ * Venom is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Venom is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Venom. If not, see .
+ */
+
+using ToxCore;
+
+namespace Venom {
+ public interface ToxSessionThread : GLib.Object {
+ public abstract void start();
+ public abstract void stop();
+ }
+
+ public class ToxSessionThreadImpl : ToxSessionThread, Object {
+ private unowned ToxSessionImpl session;
+ private unowned List bootstrapNodes;
+ private ILogger logger;
+ private bool running;
+ private bool bootstrapped;
+ private Thread session_thread = null;
+
+ public ToxSessionThreadImpl(ToxSessionImpl session, ILogger logger, List bootstrapNodes) {
+ this.session = session;
+ this.logger = logger;
+ this.bootstrapNodes = bootstrapNodes;
+ this.running = false;
+ this.bootstrapped = false;
+ logger.d("ToxSessionThread created.");
+ }
+
+ ~ToxSessionThreadImpl() {
+ stop();
+ logger.d("ToxSessionThread destroyed.");
+ }
+
+ // Background thread main function
+ private int run() {
+ logger.i("Background thread started.");
+
+ if (!bootstrapped) {
+ logger.d("Connecting to DHT Nodes:");
+ session.@lock();
+ foreach (var dht_node in bootstrapNodes) {
+ if (dht_node.is_blocked) {
+ continue;
+ }
+ logger.d(" %s".printf(dht_node.to_string()));
+ var bootstrap_err = ToxCore.ErrBootstrap.OK;
+ var ret = session.handle.bootstrap(dht_node.host, (uint16) dht_node.port, Tools.hexstring_to_bin(dht_node.pub_key), out bootstrap_err);
+ if (bootstrap_err != ToxCore.ErrBootstrap.OK || !ret) {
+ logger.i("Connecting to node %s failed: %s".printf(dht_node.to_string(), bootstrap_err.to_string()));
+ }
+ }
+ session.unlock();
+ bootstrapped = true;
+ }
+
+ var status = false;
+ var newStatus = false;
+ while (running) {
+ session.@lock();
+ newStatus = (session.handle.self_get_connection_status() != Connection.NONE);
+ session.unlock();
+ if (newStatus && !status) {
+ logger.i("Connection to dht node established.");
+ } else if (!newStatus && status) {
+ logger.i("Connection to dht node lost.");
+ }
+ status = newStatus;
+
+ session.@lock();
+ session.handle.iterate(session);
+ session.unlock();
+ Thread.usleep(session.handle.iteration_interval() * 1000);
+ }
+
+ logger.i("Background thread stopped.");
+ return 0;
+ }
+
+ // Start the background thread
+ public void start() {
+ if (running) {
+ return;
+ }
+ running = true;
+ session_thread = new Thread("worker", run);
+ }
+
+ // Stop background thread
+ public void stop() {
+ running = false;
+ join();
+ session_thread = null;
+ }
+
+ // Wait for background thread to finish
+ private void join() {
+ if (session_thread != null) {
+ session_thread.join();
+ }
+ }
+ }
+}
diff --git a/src/ui/AddContactDialog.vala b/src/ui/AddContactDialog.vala
deleted file mode 100644
index 14af09d..0000000
--- a/src/ui/AddContactDialog.vala
+++ /dev/null
@@ -1,108 +0,0 @@
-/*
- * AddContactDialog.vala
- *
- * Copyright (C) 2013-2014 Venom authors and contributors
- *
- * This file is part of Venom.
- *
- * Venom is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * Venom is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with Venom. If not, see .
- */
-
-namespace Venom {
- public class AddContactDialog : Gtk.Dialog{
- public string id {
- get { return entry_contact_id.text; }
- set { entry_contact_id.text = value; }
- }
- public string contact_alias {
- get { return entry_contact_alias.text; }
- set { entry_contact_alias.text = value; }
- }
- public string message {
- owned get { return textview_contact_message.buffer.text; }
- set { textview_contact_message.buffer.text = value; }
- }
- public int max_message_length { get; set; default = -1;}
-
- private Gtk.Entry entry_contact_id;
- private Gtk.Entry entry_contact_alias;
- private Gtk.TextView textview_contact_message;
-
- private GLib.Regex id_regex;
-
- public AddContactDialog() {
- init_widgets();
- }
-
- private void init_widgets() {
- Gtk.Builder builder = new Gtk.Builder();
- try {
- builder.add_from_resource("/org/gtk/venom/add_contact_dialog.ui");
- } catch (GLib.Error e) {
- Logger.log(LogLevel.FATAL, "Loading add contact window failed: " + e.message);
- }
-
- Gtk.Box box = builder.get_object("box") as Gtk.Box;
- this.get_content_area().add(box);
-
- entry_contact_id = builder.get_object("entry_contact_id") as Gtk.Entry;
- entry_contact_alias = builder.get_object("entry_contact_name") as Gtk.Entry;
- textview_contact_message = builder.get_object("textview_contact_message") as Gtk.TextView;
- entry_contact_id.changed.connect(on_entry_changed);
-
- on_entry_changed();
-
- textview_contact_message.buffer.insert_text.connect(on_insert_text);
-
- try {
- id_regex = new GLib.Regex("^[[:xdigit:]]*$");
- } catch (RegexError re) {
- Logger.log(LogLevel.FATAL, "Failed to compile regex:" + re.message);
- }
-
- this.add_buttons("_Cancel", Gtk.ResponseType.CANCEL, "_Ok", Gtk.ResponseType.OK, null);
- this.set_default_response(Gtk.ResponseType.OK);
- this.title = _("Add contact");
- this.set_default_size(400, 250);
- }
-
- private void on_insert_text(ref Gtk.TextIter pos, string new_text, int new_text_length) {
- int buffer_length = textview_contact_message.buffer.text.length;
- if(max_message_length < 0 || buffer_length <= max_message_length)
- return;
-
- //TODO cut off too long messages
- }
-
- private void on_entry_changed() {
- if(id == null || id == "") {
- entry_contact_id.secondary_icon_tooltip_text = _("No ID given");
- entry_contact_id.secondary_icon_name = "emblem-important-symbolic";
- } else {
- string stripped_id = Tools.remove_whitespace(id);
- if (stripped_id.length == Tox.FRIEND_ADDRESS_SIZE * 2) {
- if (id_regex != null && !id_regex.match(stripped_id)) {
- entry_contact_id.secondary_icon_tooltip_text = _("ID contains invalid characters");
- entry_contact_id.secondary_icon_name = "emblem-important-symbolic";
- } else {
- entry_contact_id.secondary_icon_name = "emblem-ok-symbolic";
- entry_contact_id.secondary_icon_tooltip_text = _("Valid ID size");
- }
- } else {
- entry_contact_id.secondary_icon_pixbuf = null;
- }
- }
- }
- }
-}
diff --git a/src/ui/ChatMessage.vala b/src/ui/ChatMessage.vala
deleted file mode 100644
index b098389..0000000
--- a/src/ui/ChatMessage.vala
+++ /dev/null
@@ -1,75 +0,0 @@
-/*
- * Copyright (C) 2013 Venom authors and contributors
- *
- * This file is part of Venom.
- *
- * Venom is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * Venom is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with Venom. If not, see .
- */
-
-namespace Venom {
- public class ChatMessage : Gtk.Box {
- private Gtk.Label name_label;
- private Gtk.Label message_label;
- private Gtk.Label date_label;
-
- public ChatMessage(IMessage message, bool short_names, bool following, int offset){
- init_widgets();
-
- if( message.is_action ) {
- name_label.set_text( message.get_sender_plain() );
- } else if(!following) {
- if(message.message_direction == MessageDirection.OUTGOING) {
- name_label.get_style_context().add_class("own_name");
- }
- if(short_names) {
- name_label.set_text( Tools.shorten_name( message.get_sender_plain() ) );
- } else {
- name_label.set_text( message.get_sender_plain() );
- }
- } else {
- name_label.set_text("");
- name_label.set_size_request(offset, -1);
- }
- string markup_message_text = Tools.markup_uris(message.get_message_plain());
- message_label.set_markup( markup_message_text );
- date_label.set_text( message.get_time_plain() );
- }
-
- public int get_name_label_width() {
- Gtk.Requisition req;
- name_label.get_preferred_size(null, out req);
- return req.width;
- }
-
- private void init_widgets() {
- this.get_style_context().add_class("message_entry");
- this.spacing = 12;
- this.margin_left = 12;
- this.margin_right = 12;
- name_label = new Gtk.Label(null);
- name_label.set_alignment(1,0);
- message_label = new Gtk.Label(null);
- message_label.wrap_mode = Pango.WrapMode.WORD_CHAR;
- message_label.wrap = true;
- message_label.selectable = true;
- message_label.set_alignment(0,0);
- date_label = new Gtk.Label(null);
- date_label.get_style_context().add_class("date_label");
- date_label.set_alignment(0,0);
- this.pack_start(name_label, false);
- this.pack_start(message_label, false);
- this.pack_end(date_label, false);
- }
- }
-}
diff --git a/src/ui/Client.vala b/src/ui/Client.vala
deleted file mode 100644
index a191c61..0000000
--- a/src/ui/Client.vala
+++ /dev/null
@@ -1,189 +0,0 @@
-/*
- * Client.vala
- *
- * Copyright (C) 2013-2014 Venom authors and contributors
- *
- * This file is part of Venom.
- *
- * Venom is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * Venom is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with Venom. If not, see .
- */
-namespace Venom {
- class Client : Gtk.Application {
- private const GLib.ActionEntry app_entries[] =
- {
- { "preferences", on_preferences },
- { "help", on_help },
- { "about", on_about },
- { "quit", on_quit }
- };
- private ContactListWindow contact_list_window;
- private SettingsWindow settings_window;
- private Gtk.StatusIcon tray_icon;
-
- public Client() {
- // call gobject base constructor
- GLib.Object(
- application_id: "im.tox.venom",
- flags: GLib.ApplicationFlags.HANDLES_OPEN
- );
- }
-
- ~Client() {
- // FIXME Workaround for some DEs keeping
- // one instance of the contactlistwindow alive
- if(contact_list_window != null) {
- contact_list_window.cleanup();
- }
- }
-
- private ContactListWindow get_contact_list_window() {
- if( get_windows () == null ) {
- contact_list_window = new ContactListWindow(this);
-
- // Create menu
- GLib.Menu menu_prefs = new GLib.Menu();
- GLib.MenuItem item = new GLib.MenuItem ("P_references", "app.preferences");
- menu_prefs.append_item(item);
-
- GLib.Menu menu_common = new GLib.Menu();
- item = new GLib.MenuItem ("_Help", "app.help");
- item.set_attribute("accel", "s", "F1");
- menu_common.append_item(item);
-
- item = new GLib.MenuItem ("_About", "app.about");
- menu_common.append_item(item);
-
- item = new GLib.MenuItem ("_Quit", "app.quit");
- item.set_attribute("accel", "s", "q");
- menu_common.append_item(item);
-
- GLib.Menu menu = new GLib.Menu();
- menu.append_section(null, menu_prefs);
- menu.append_section(null, menu_common);
-
- set_app_menu(menu);
-
- create_tray_menu();
- tray_icon = new Gtk.StatusIcon.from_icon_name("venom");
- tray_icon.set_tooltip_text ("Venom");
- Settings.instance.bind_property(Settings.TRAY_KEY, tray_icon, "visible", BindingFlags.SYNC_CREATE);
- tray_icon.activate.connect(on_trayicon_activate);
- tray_icon.popup_menu.connect(on_trayicon_popup_menu);
- }
- return contact_list_window;
- }
-
- private Gtk.Menu tray_menu;
- private void create_tray_menu() {
- tray_menu = new Gtk.Menu();
- Gtk.MenuItem tray_menu_show = new Gtk.MenuItem.with_mnemonic(_("_Show/Hide Venom"));
- tray_menu_show.activate.connect(on_trayicon_activate);
- tray_menu.append(tray_menu_show);
- Gtk.MenuItem tray_menu_quit = new Gtk.MenuItem.with_mnemonic(_("_Quit"));
- tray_menu_quit.activate.connect(simple_on_quit);
- tray_menu.append(tray_menu_quit);
- tray_menu.show_all();
- }
-
- private void on_trayicon_activate() {
- var w = get_contact_list_window();
- if(w.visible) {
- w.hide();
- } else {
- w.deiconify(); //Avoid the window to stay hid when "minimized on tray"
- w.show();
- }
- }
-
- private void on_trayicon_popup_menu(uint button, uint time) {
- tray_menu.popup(null, null, null, button, time);
- }
-
- protected override void startup() {
- add_action_entries(app_entries, this);
- base.startup();
- }
-
- private void show_notification_for_message(IMessage m) {
- if(get_contact_list_window().is_active || !Settings.instance.enable_notify) {
- return;
- }
- Notification.show_notification_for_message(m);
- }
-
- protected override void activate() {
- hold();
-
- var window = get_contact_list_window();
- window.incoming_message.connect(show_notification_for_message);
- window.incoming_group_message.connect(show_notification_for_message);
- window.incoming_action.connect(show_notification_for_message);
- window.incoming_group_action.connect(show_notification_for_message);
-
- window.present();
- release();
- }
-
- protected override void open(GLib.File[] files, string hint) {
- hold();
- get_contact_list_window().present();
- //FIXME allow names without tox:// prefix on command line
- contact_list_window.add_contact(files[0].get_uri());
- release();
- }
-
- private void on_preferences(GLib.SimpleAction action, GLib.Variant? parameter) {
- if(settings_window == null) {
- settings_window = new SettingsWindow(contact_list_window);
- settings_window.destroy.connect( () => {settings_window = null;});
- settings_window.show_all();
- } else {
- settings_window.present();
- }
- }
-
- private void on_help(GLib.SimpleAction action, GLib.Variant? parameter) {
- Gtk.MessageDialog dialog = new Gtk.MessageDialog(
- contact_list_window,
- Gtk.DialogFlags.MODAL,
- Gtk.MessageType.INFO,
- Gtk.ButtonsType.OK,
- _("There is currently no help available"),
- null
- );
- dialog.transient_for = contact_list_window;
- dialog.run();
- dialog.destroy();
- }
-
- private AboutDialog about_dialog;
- private void on_about(GLib.SimpleAction action, GLib.Variant? parameter) {
- if(about_dialog == null)
- about_dialog = new AboutDialog();
- about_dialog.transient_for = contact_list_window;
- about_dialog.modal = true;
- about_dialog.run();
- about_dialog.hide();
- }
-
- private void on_quit(GLib.SimpleAction action, GLib.Variant? parameter) {
- simple_on_quit();
- }
- private void simple_on_quit() {
- if(contact_list_window != null) {
- contact_list_window.destroy();
- }
- }
- }
-}
diff --git a/src/ui/ContactFilter.vala b/src/ui/ContactFilter.vala
deleted file mode 100644
index 14ef7b3..0000000
--- a/src/ui/ContactFilter.vala
+++ /dev/null
@@ -1,43 +0,0 @@
-/*
- * ContactFilter.vala
- *
- * Copyright (C) 2013-2014 Venom authors and contributors
- *
- * This file is part of Venom.
- *
- * Venom is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * Venom is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with Venom. If not, see .
- */
-
-namespace Venom {
- interface ContactFilter : GLib.Object {
- public abstract bool filter_func(Gtk.TreeModel model, Gtk.TreeIter iter);
- }
- class ContactFilterAll : GLib.Object, ContactFilter {
- public bool filter_func(Gtk.TreeModel model, Gtk.TreeIter iter) {
- return true;
- }
- }
- class ContactFilterOnline : GLib.Object, ContactFilter {
- public bool filter_func(Gtk.TreeModel model, Gtk.TreeIter iter) {
- GLib.Value val;
- model.get_value(iter, 0, out val);
- if(val.get_object() is Contact) {
- return (val as Contact).online;
- } else if (val.get_object() is GroupChat) {
- return (val as GroupChat).peer_count > 0;
- }
- return true;
- }
- }
-}
diff --git a/src/ui/ContactListCellRenderer.vala b/src/ui/ContactListCellRenderer.vala
deleted file mode 100644
index bdc6c35..0000000
--- a/src/ui/ContactListCellRenderer.vala
+++ /dev/null
@@ -1,187 +0,0 @@
-/*
- * ContactListCellRenderer.vala
- *
- * Copyright (C) 2013-2014 Venom authors and contributors
- *
- * This file is part of Venom.
- *
- * Venom is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * Venom is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with Venom. If not, see .
- */
-
-namespace Venom {
- public class ContactListCellRenderer : Gtk.CellRenderer {
- public IContact entry { get; set; }
- private static Gdk.RGBA unread_message_bgcolor = Gdk.RGBA() { red = 0.419607843, green = 0.760784314, blue = 0.376470588, alpha = 1.0 };
- private static Gdk.RGBA unread_message_fgcolor = Gdk.RGBA() { red = 0, green = 0, blue = 0, alpha = 1.0 };
-
- public override void get_size(Gtk.Widget widget, Gdk.Rectangle? cell_area, out int x_offset, out int y_offset, out int width, out int height) {
- x_offset = 0;
- y_offset = 0;
- width = 50;
- height = 59;
- }
-
- public override void render(Cairo.Context ctx, Gtk.Widget widget, Gdk.Rectangle background_area, Gdk.Rectangle cell_area, Gtk.CellRendererState flags) {
- int y = 6 + cell_area.y;
- Gtk.StateFlags state_flags = get_state(widget, flags);
- Pango.Rectangle ink_rect = render_name(ctx, widget, background_area, cell_area, y, state_flags);
- y += ink_rect.height;
- render_status(ctx, widget, background_area, cell_area, y);
- render_image(ctx, widget, background_area, cell_area, y);
- render_userstatus(ctx, widget, background_area, cell_area);
- render_unread_messages(ctx, widget, background_area, cell_area);
- }
-
- private void render_image(Cairo.Context ctx, Gtk.Widget widget, Gdk.Rectangle background_area, Gdk.Rectangle cell_area, int y_offset) {
- Gdk.Pixbuf? icon;
- if(entry is Contact) {
- Contact contact = (Contact)entry;
- icon = contact.image != null ? contact.image : ResourceFactory.instance.default_contact;
- } else {
- GroupChat groupchat = (GroupChat)entry;
- icon = groupchat.image != null ? groupchat.image : ResourceFactory.instance.default_groupchat;
- }
- Gdk.Rectangle image_rect = {8, 9 + background_area.y, 44, 41};
- if(icon != null) {
- Gdk.cairo_rectangle(ctx, image_rect);
- Gdk.cairo_set_source_pixbuf(ctx, icon, image_rect.x, image_rect.y);
- ctx.fill();
- }
- }
-
- private void render_userstatus(Cairo.Context ctx, Gtk.Widget widget, Gdk.Rectangle background_area, Gdk.Rectangle cell_area) {
- Gdk.Pixbuf? status = null;
-
- if(entry is Contact) {
- Contact contact = (Contact)entry;
-
- if(!contact.online) {
- status = contact.unread_messages > 0 ? ResourceFactory.instance.offline_glow : ResourceFactory.instance.offline;
- }
- else {
- switch(contact.user_status) {
- case Tox.UserStatus.NONE:
- status = contact.unread_messages > 0 ? ResourceFactory.instance.online_glow : ResourceFactory.instance.online;
- break;
- case Tox.UserStatus.AWAY:
- status = contact.unread_messages > 0 ? ResourceFactory.instance.away_glow : ResourceFactory.instance.away;
- break;
- case Tox.UserStatus.BUSY:
- status = contact.unread_messages > 0 ? ResourceFactory.instance.busy_glow : ResourceFactory.instance.busy;
- break;
- case Tox.UserStatus.INVALID:
- status = contact.unread_messages > 0 ? ResourceFactory.instance.offline_glow : ResourceFactory.instance.offline;
- break;
- }
- }
- } else if(entry is GroupChat) {
- GroupChat groupchat = (GroupChat)entry;
- if(groupchat.peer_count > 0) {
- status = groupchat.unread_messages > 0 ? ResourceFactory.instance.online_glow : ResourceFactory.instance.online;
- } else {
- status = groupchat.unread_messages > 0 ? ResourceFactory.instance.offline_glow :ResourceFactory.instance.offline;
- }
- }
- if(status != null) {
- Gdk.Rectangle image_rect = {cell_area.x + cell_area.width - 24, cell_area.y + cell_area.height / 2 - 13, 26, 26};
- Gdk.cairo_rectangle(ctx, image_rect);
- Gdk.cairo_set_source_pixbuf(ctx, status, image_rect.x, image_rect.y);
- ctx.fill();
- }
- }
-
- private Pango.Rectangle? render_name(Cairo.Context ctx, Gtk.Widget widget, Gdk.Rectangle background_area, Gdk.Rectangle cell_area, int y_offset, Gtk.StateFlags state_flags) {
- Pango.Rectangle? ink_rect, logical_rect;
- Pango.FontDescription font = new Pango.FontDescription();
- Pango.Layout layout = widget.create_pango_layout(null);
- layout.set_font_description(font);
- Gdk.RGBA color = widget.get_style_context().get_color(state_flags);
-
- layout.set_markup(entry.get_name_string(), -1);
- layout.set_ellipsize(Pango.EllipsizeMode.END);
- layout.set_width((cell_area.width - 58 - 26) * Pango.SCALE);
- layout.get_pixel_extents(out ink_rect, out logical_rect);
-
- if (ctx != null) {
- ctx.save();
- Gdk.cairo_set_source_rgba(ctx, color);
- ctx.move_to(cell_area.x + 58, cell_area.y + cell_area.height / 2 - ink_rect.height - 8);
- Pango.cairo_show_layout(ctx, layout);
- ctx.restore();
- }
- return ink_rect;
- }
-
- private Pango.Rectangle render_status(Cairo.Context ctx, Gtk.Widget widget, Gdk.Rectangle background_area, Gdk.Rectangle cell_area, int y_offset) {
- Pango.Rectangle? ink_rect, logical_rect;
- Pango.FontDescription font = new Pango.FontDescription();
- Pango.Layout layout = widget.create_pango_layout(null);
- layout.set_font_description(font);
- Gdk.RGBA color = widget.get_style_context().get_color(Gtk.StateFlags.NORMAL);
- //FIXME find a better way for this (css styling if possible)
- color.red -= 0.4;
- color.green -= 0.4;
- color.blue -= 0.4;
- layout.set_markup(entry.get_status_string(), -1);
- layout.set_ellipsize(Pango.EllipsizeMode.END);
- layout.set_width((cell_area.width - 58 - 26) * Pango.SCALE);
- layout.get_pixel_extents(out ink_rect, out logical_rect);
-
- if (ctx != null) {
- ctx.save();
- Gdk.cairo_set_source_rgba(ctx, color);
- ctx.move_to(cell_area.x + 58, cell_area.y + cell_area.height / 2 - 2);
- Pango.cairo_show_layout(ctx, layout);
- ctx.restore();
- }
- return ink_rect;
- }
- private void render_unread_messages(Cairo.Context ctx, Gtk.Widget widget, Gdk.Rectangle background_area, Gdk.Rectangle cell_area) {
- int unread_messages = 0;
- if(entry is Contact) {
- unread_messages = ((Contact)entry).unread_messages;
- } else if(entry is GroupChat) {
- unread_messages = ((GroupChat)entry).unread_messages;
- }
- if(unread_messages == 0) {
- return;
- }
- string str = unread_messages < 10 ? unread_messages.to_string() : "+";
-
- Pango.Rectangle? ink_rect, logical_rect;
- Gdk.Rectangle image_rect_border = {cell_area.x + cell_area.width - 24 , cell_area.y + cell_area.height / 2, 13, 13};
- Gdk.Rectangle image_rect = {cell_area.x + cell_area.width - 23 , cell_area.y + cell_area.height / 2 + 1, 11, 11};
-
- Pango.FontDescription font = new Pango.FontDescription();
- font.set_absolute_size(10 * Pango.SCALE);
- Pango.Layout layout = widget.create_pango_layout(null);
- layout.set_font_description(font);
- layout.set_markup("%s".printf(str), -1);
- layout.get_pixel_extents(out ink_rect, out logical_rect);
-
- ctx.save();
- Gdk.cairo_rectangle(ctx, image_rect_border);
- Gdk.cairo_set_source_rgba(ctx, unread_message_fgcolor);
- ctx.fill();
- Gdk.cairo_rectangle(ctx, image_rect);
- Gdk.cairo_set_source_rgba(ctx, unread_message_bgcolor);
- ctx.fill();
- Gdk.cairo_set_source_rgba(ctx, unread_message_fgcolor);
- //FIXME correct centering, maybe fixed-size font
- ctx.move_to(image_rect.x + image_rect.width / 2 - logical_rect.width / 2, image_rect.y + image_rect.height / 2 - logical_rect.height / 2);
- Pango.cairo_show_layout(ctx, layout);
- ctx.restore();
- }
- }
-}
diff --git a/src/ui/ContactListTreeView.vala b/src/ui/ContactListTreeView.vala
deleted file mode 100644
index 9fcf402..0000000
--- a/src/ui/ContactListTreeView.vala
+++ /dev/null
@@ -1,128 +0,0 @@
-/*
- * Copyright (C) 2013-2014 Venom authors and contributors
- *
- * This file is part of Venom.
- *
- * Venom is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * Venom is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with Venom. If not, see .
- */
-
-namespace Venom {
- public class ContactListTreeView : Gtk.TreeView {
- Gtk.ListStore list_store_contacts;
- Gtk.TreeViewColumn name_column;
-
- public signal void entry_activated(IContact c);
-
- public ContactListTreeView() {
- list_store_contacts = new Gtk.ListStore (1, typeof(IContact));
-
- name_column = new Gtk.TreeViewColumn();
- ContactListCellRenderer name_column_cell = new ContactListCellRenderer();
- name_column.pack_start(name_column_cell, true);
-
- name_column.add_attribute (name_column_cell, "entry", 0);
-
- set_model (list_store_contacts);
-
- append_column(name_column);
-
- Gtk.TreeSelection s = get_selection();
- s.set_mode(Gtk.SelectionMode.SINGLE);
- s.set_select_function(on_row_selected);
-
- query_tooltip.connect_after(modify_tooltip);
- has_tooltip = true;
-
- //hide headers
- set_headers_visible(false);
- can_focus = false;
- }
- private bool on_row_selected( Gtk.TreeSelection selection, Gtk.TreeModel model, Gtk.TreePath path, bool path_currently_selected ) {
- Gtk.TreeIter iter;
- model.get_iter(out iter, path);
- GLib.Value val;
- model.get_value(iter, 0, out val);
- entry_activated(val as IContact);
- return true;
- }
-
- private bool modify_tooltip(int x, int y, bool keyboard_tooltip, Gtk.Tooltip tooltip) {
- Gtk.TreeModel model;
- Gtk.TreePath path;
- Gtk.TreeIter iter;
- if(!get_tooltip_context(ref x, ref y, keyboard_tooltip, out model, out path, out iter))
- return false;
- if(model == null)
- return false;
- GLib.Value v;
- model.get_value(iter, 0, out v);
- GLib.Object o = v as Object;
- if(o is IContact) {
- IContact c = o as IContact;
- tooltip.set_markup(c.get_tooltip_string());
- } else {
- return false;
- }
- set_tooltip_row(tooltip, path);
- return true;
- }
-
- public void add_entry(IContact c) {
- Gtk.TreeIter iter;
- list_store_contacts.append(out iter);
- list_store_contacts.set(iter, 0, c);
- can_focus = true;
- }
-
- public void update_entry(IContact c) {
- Gtk.TreeIter? iter = find_iter(c);
- list_store_contacts.row_changed(list_store_contacts.get_path(iter), iter);
- }
-
- public void remove_entry(IContact c) {
- Gtk.TreeIter iter = find_iter(c);
- list_store_contacts.remove(iter);
- columns_changed();
- if(list_store_contacts.iter_n_children(null) == 0)
- can_focus = false;
- }
-
- public IContact? get_selected_entry() {
- Gtk.TreeSelection selection = get_selection();
- if(selection == null)
- return null;
- Gtk.TreeModel model;
- Gtk.TreeIter iter;
- if (!selection.get_selected(out model, out iter))
- return null;
- GLib.Value val;
- model.get_value(iter, 0, out val);
- return val as IContact;
- }
-
- private Gtk.TreeIter? find_iter(IContact c) {
- Gtk.TreeIter iter;
- list_store_contacts.get_iter_first(out iter);
- do {
- GLib.Value val;
- list_store_contacts.get_value(iter, 0, out val);
- if(val.get_object() == c)
- return iter;
- } while( list_store_contacts.iter_next(ref iter) );
-
- // not found
- return null;
- }
- }
-}
diff --git a/src/ui/ContactListWindow.vala b/src/ui/ContactListWindow.vala
deleted file mode 100644
index f55f367..0000000
--- a/src/ui/ContactListWindow.vala
+++ /dev/null
@@ -1,1258 +0,0 @@
-/*
- * ContactListWindow.vala
- *
- * Copyright (C) 2013-2014 Venom authors and contributors
- *
- * This file is part of Venom.
- *
- * Venom is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * Venom is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with Venom. If not, see .
- */
-
-namespace Venom {
- public class ContactListWindow : Gtk.ApplicationWindow {
- private const GLib.ActionEntry win_entries[] =
- {
- { "edit-user", edit_user_information }
- };
- private const GLib.ActionEntry app_entries[] =
- {
- { "copy-id", copy_id_to_clipboard }
- };
- // Containers
- private GLib.HashTable conversation_widgets;
- private GLib.HashTable group_conversation_widgets;
- // Tox session wrapper
- private ToxSession session;
- private UserStatus user_status = UserStatus.OFFLINE;
- private Gtk.ImageMenuItem menuitem_status;
-
- // Widgets
- private Gtk.Image image_status;
- private Gtk.Spinner spinner_status;
- private Gtk.Image image_userimage;
- private EditableLabel label_name;
- private EditableLabel label_status;
- private ContactListTreeView contact_list_tree_view;
- private Gtk.ComboBox combobox_status;
- private Gtk.Notebook notebook_conversations;
- private Gtk.Menu menu_user;
- private Gtk.ToggleButton button_user;
-
- private bool cleaned_up = false;
-
- private string our_title = "";
-
- // Signals
- public signal void contact_added(Contact c);
- public signal void contact_changed(Contact c);
- public signal void contact_removed(Contact c);
-
- public signal void groupchat_added(GroupChat g);
- public signal void groupchat_changed(GroupChat g);
- public signal void groupchat_removed(GroupChat g);
-
- public signal void incoming_message(Message m);
- public signal void incoming_action(ActionMessage m);
- public signal void incoming_group_message(GroupMessage m);
- public signal void incoming_group_action(GroupActionMessage m);
-
- // Default Constructor
- public ContactListWindow (Gtk.Application application) {
- GLib.Object(application:application);
- this.conversation_widgets = new GLib.HashTable(null, null);
- this.group_conversation_widgets = new GLib.HashTable(null, null);
-
- init_theme();
- init_session();
- init_widgets();
- init_signals();
- init_contacts();
- init_save_session_hooks();
- init_user();
-
- on_ownconnectionstatus(false);
-
- Logger.log(LogLevel.INFO, "ID: " + Tools.bin_to_hexstring(session.get_address()));
- if(ResourceFactory.instance.offline_mode) {
- set_userstatus(UserStatus.OFFLINE);
- } else {
- set_userstatus(UserStatus.ONLINE);
- }
- }
-
- // Destructor
- ~ContactListWindow() {
- cleanup();
- }
-
- public void cleanup() {
- if(cleaned_up)
- return;
- Logger.log(LogLevel.DEBUG, "Ending session...");
- // Stop background thread
- session.stop();
- // wait for background thread to finish
- session.join();
-
- // Save session before shutdown
- save_session();
-
- Logger.log(LogLevel.DEBUG, "Session ended gracefully.");
- cleaned_up = true;
- }
-
- private void save_session() {
- Logger.log(LogLevel.INFO, "Saving tox session data");
- try {
- session.save_to_file(ResourceFactory.instance.data_filename);
- } catch (Error e) {
- Logger.log(LogLevel.ERROR, "Saving session file failed: " + e.message);
- }
-
- }
-
- private void init_theme() {
- Gtk.CssProvider provider = new Gtk.CssProvider();
- try {
- provider.load_from_path(ResourceFactory.instance.default_theme_filename);
- } catch (Error e) {
- string message = _("Could not read theme from \"%s\"").printf(ResourceFactory.instance.default_theme_filename);
- Logger.log(LogLevel.ERROR, message);
- UITools.show_error_dialog(message, e.message, this);
- return;
- }
-
- Gdk.Screen screen = Gdk.Screen.get_default();
- Gtk.StyleContext.add_provider_for_screen(screen, provider, Gtk.STYLE_PROVIDER_PRIORITY_APPLICATION);
- }
-
- // Create a new session, load/create session data
- private void init_session() {
- session = new ToxSession();
- try {
- session.load_from_file(ResourceFactory.instance.data_filename);
- } catch (Error e) {
- Logger.log(LogLevel.INFO, "Could not load session data (%s), creating new one.".printf(e.message));
-
- session.set_name(ResourceFactory.instance.default_username);
- session.set_status_message(ResourceFactory.instance.default_statusmessage);
-
- save_session();
- }
- }
-
- // Initialize widgets
- private void init_widgets() {
- // Set up Window
- set_default_size(Settings.instance.contactlist_width, Settings.instance.contactlist_height);
- show_menubar = false;
- add_action_entries(win_entries, this);
- application.add_action_entries(app_entries, this);
- try {
- Gtk.IconTheme theme = Gtk.IconTheme.get_default();
- theme.append_search_path(Path.build_filename("share", "pixmaps"));
- theme.append_search_path(Path.build_filename("..", "share", "pixmaps"));
- set_default_icon(Gtk.IconTheme.get_default().load_icon("venom", 48, 0));
- } catch (Error e) {
- Logger.log(LogLevel.ERROR, "Error while loading icon: " + e.message);
- }
- set_title_from_status(user_status);
-
- // Load widgets from file
- Gtk.Builder builder = new Gtk.Builder();
- try {
- builder.add_from_resource("/org/gtk/venom/contact_list.ui");
- } catch (GLib.Error e) {
- Logger.log(LogLevel.FATAL, "Loading contact list failed: " + e.message);
- }
-
- Gtk.Paned paned = builder.get_object("paned") as Gtk.Paned;
- this.add(paned);
-
- image_status = builder.get_object("image_status") as Gtk.Image;
- spinner_status = builder.get_object("spinner_status") as Gtk.Spinner;
- image_userimage = builder.get_object("image_userimage") as Gtk.Image;
-
- Gtk.Label label_name_child = builder.get_object("label_username") as Gtk.Label;
- Gtk.Label label_status_child = builder.get_object("label_userstatus") as Gtk.Label;
- Gtk.Box box_self_info_text = builder.get_object("box_self_info_text") as Gtk.Box;
- box_self_info_text.remove(label_name_child);
- box_self_info_text.remove(label_status_child);
- label_name = new EditableLabel.with_label(label_name_child);
- label_status = new EditableLabel.with_label(label_status_child);
- box_self_info_text.pack_start(label_name, false);
- box_self_info_text.pack_start(label_status, false);
- box_self_info_text.show_all();
-
- combobox_status = builder.get_object("combobox_status") as Gtk.ComboBox;
- Gtk.ListStore liststore_status = new Gtk.ListStore (2, typeof(string), typeof(ContactFilter));
- combobox_status.set_model(liststore_status);
-
- ContactFilter filter_online = new ContactFilterOnline();
- ContactFilter filter_all = new ContactFilterAll();
- ContactFilter filter_default = filter_all;
- // Add our connection status to the treeview
- Gtk.TreeIter iter;
- liststore_status.append(out iter);
- liststore_status.set(iter, 0, _("Online"), 1, filter_online, -1);
- liststore_status.append(out iter);
- liststore_status.set(iter, 0, _("All"), 1, filter_all, -1);
- combobox_status.set_active_iter(iter);
-
- // Add cellrenderer
- Gtk.CellRendererText cell_renderer_status = new Gtk.CellRendererText();
- combobox_status.pack_start(cell_renderer_status, true);
- combobox_status.add_attribute(cell_renderer_status, "text", 0);
-
- Gtk.Image image_add_contact = builder.get_object("image_add_contact") as Gtk.Image;
- Gtk.Image image_group_chat = builder.get_object("image_group_chat") as Gtk.Image;
- Gtk.Image image_preferences = builder.get_object("image_preferences") as Gtk.Image;
- Gtk.Image image_filetransfer = builder.get_object("image_filetransfer") as Gtk.Image;
-
- Gtk.ImageMenuItem menuitem_edit_info = builder.get_object("menuitem_edit_info") as Gtk.ImageMenuItem;
- Gtk.ImageMenuItem menuitem_copy_id = builder.get_object("menuitem_copy_id") as Gtk.ImageMenuItem;
-
- menuitem_status = builder.get_object("menuitem_status") as Gtk.ImageMenuItem;
- Gtk.ImageMenuItem menuitem_status_online = builder.get_object("menuitem_status_online") as Gtk.ImageMenuItem;
- Gtk.ImageMenuItem menuitem_status_away = builder.get_object("menuitem_status_away") as Gtk.ImageMenuItem;
- Gtk.ImageMenuItem menuitem_status_busy = builder.get_object("menuitem_status_busy") as Gtk.ImageMenuItem;
- Gtk.ImageMenuItem menuitem_status_offline = builder.get_object("menuitem_status_offline") as Gtk.ImageMenuItem;
-
- (menuitem_status.image as Gtk.Image).set_from_pixbuf(ResourceFactory.instance.offline);
- (menuitem_status_online.image as Gtk.Image).set_from_pixbuf(ResourceFactory.instance.online);
- (menuitem_status_away.image as Gtk.Image).set_from_pixbuf(ResourceFactory.instance.away);
- (menuitem_status_busy.image as Gtk.Image).set_from_pixbuf(ResourceFactory.instance.busy);
- (menuitem_status_offline.image as Gtk.Image).set_from_pixbuf(ResourceFactory.instance.offline);
-
- Gtk.MenuItem menuitem_export = builder.get_object("menuitem_export") as Gtk.MenuItem;
- Gtk.MenuItem menuitem_import = builder.get_object("menuitem_import") as Gtk.MenuItem;
-
- Gtk.ImageMenuItem menuitem_about = builder.get_object("menuitem_about") as Gtk.ImageMenuItem;
- Gtk.ImageMenuItem menuitem_quit = builder.get_object("menuitem_quit") as Gtk.ImageMenuItem;
-
- image_status.set_from_pixbuf(ResourceFactory.instance.offline);
- image_userimage.set_from_pixbuf(ResourceFactory.instance.default_contact);
-
- image_add_contact.set_from_pixbuf(ResourceFactory.instance.add);
- image_group_chat.set_from_pixbuf(ResourceFactory.instance.groupchat);
- image_preferences.set_from_pixbuf(ResourceFactory.instance.settings);
- image_filetransfer.set_from_pixbuf(ResourceFactory.instance.filetransfer);
-
- // Create and add custom treeview
- contact_list_tree_view = new ContactListTreeView();
- contact_list_tree_view.show_all();
-
- Gtk.TreeModel m = contact_list_tree_view.model;
- Gtk.TreeModelFilter contact_list_tree_model_filter = new Gtk.TreeModelFilter(m, null);
- contact_list_tree_model_filter.set_visible_func(filter_default.filter_func);
- contact_list_tree_view.model = contact_list_tree_model_filter;
-
- Gtk.ScrolledWindow scrolled_window_contact_list = builder.get_object("scrolled_window_contact_list") as Gtk.ScrolledWindow;
- scrolled_window_contact_list.add(contact_list_tree_view);
-
- menu_user = builder.get_object("menu_user") as Gtk.Menu;
- menu_user.attach_widget = this;
- button_user = builder.get_object("button_user") as Gtk.ToggleButton;
- Gtk.Button button_add_contact = builder.get_object("button_add_contact") as Gtk.Button;
- Gtk.Button button_group_chat = builder.get_object("button_group_chat") as Gtk.Button;
-
- // poor man's Gtk.MenuButton
- //FIXME choose monitor to display this on
- button_user.clicked.connect( () => {
- if(button_user.active) {
- menu_user.popup(null,
- null,
- user_button_menu_position_function,
- 0,
- 0);
- }
- });
- menu_user.deactivate.connect( () => {
- button_user.active = false;
- });
- /*button_user.button_press_event.connect( (widget, event) => {
- if(event.type == Gdk.EventType.BUTTON_PRESS) {
- if(event.button == Gdk.BUTTON_PRIMARY)
- menu_user.popup(null, null, null, event.button, event.time);
- }
- return false;
- });*/
- button_add_contact.clicked.connect(() => { add_contact(); });
- button_group_chat.clicked.connect(button_group_chat_clicked);
-
- // Workaround for gtk+ 3.4 MenuItems not deriving from Gtk.Actionable
- menuitem_copy_id.activate.connect( () => {application.activate_action("copy-id", null);});
- menuitem_edit_info.activate.connect(() => {activate_action("edit-user", null);});
- menuitem_export.activate.connect(() => {UITools.export_datafile(this, session);});
- menuitem_import.activate.connect(() => {UITools.import_datafile(this, session);});
- menuitem_about.activate.connect(() => {application.activate_action("about", null);});
- menuitem_quit.activate.connect( () => {application.activate_action("quit", null);});
-
- menuitem_status_online.activate.connect( () => { set_userstatus(UserStatus.ONLINE); } );
- menuitem_status_away.activate.connect( () => { set_userstatus(UserStatus.AWAY); } );
- menuitem_status_busy.activate.connect( () => { set_userstatus(UserStatus.BUSY); } );
- menuitem_status_offline.activate.connect( () => { set_userstatus(UserStatus.OFFLINE); } );
-
- notebook_conversations = builder.get_object("notebook_conversations") as Gtk.Notebook;
- }
-
- // Connect
- private void init_signals() {
- // Session signals
- session.on_friend_request.connect(this.on_friendrequest);
- session.on_friend_message.connect(this.on_friendmessage);
- session.on_friend_action.connect(this.on_action);
- session.on_name_change.connect(this.on_namechange);
- session.on_status_message.connect(this.on_statusmessage);
- session.on_user_status.connect(this.on_userstatus);
- session.on_read_receipt.connect(this.on_read_receipt);
- session.on_connection_status.connect(this.on_connectionstatus);
- session.on_own_connection_status.connect(this.on_ownconnectionstatus);
- session.on_own_user_status.connect(this.on_ownuserstatus);
- session.on_typing_change.connect(this.on_typing_change);
-
- //Window signals
- this.delete_event.connect((e) => {
- if(Settings.instance.enable_tray) {
- this.hide();
- return true;
- }
- return false;
- });
-
- this.window_state_event.connect( (e) => {
- if ((e.new_window_state == Gdk.WindowState.ICONIFIED) && Settings.instance.enable_tray){
- this.hide();
- return true;
- }
- return false;
- } ) ;
-
- //groupmessage signals
- session.on_group_invite.connect(this.on_group_invite);
- session.on_group_message.connect(this.on_group_message);
- session.on_group_action.connect(this.on_group_action);
- session.on_group_peer_changed.connect(this.on_group_peer_changed);
-
- //file signals
- session.on_file_sendrequest.connect(this.on_file_sendrequest);
- session.on_file_control.connect(this.on_file_control_request);
- session.on_file_data.connect(this.on_file_data);
-
- // Contact list treeview signals
- contact_added.connect(contact_list_tree_view.add_entry);
- groupchat_added.connect(contact_list_tree_view.add_entry);
-
- contact_changed.connect( (c) => {
- session.save_extended_contact_data(c);
- contact_list_tree_view.update_entry(c);
- ConversationWidget w = conversation_widgets[c.friend_id];
- if(w != null)
- w.update_contact();
- } );
- groupchat_changed.connect( (g) => {
- contact_list_tree_view.update_entry(g);
- GroupConversationWidget w = group_conversation_widgets[g.group_id];
- if(w != null)
- w.update_groupchat_info();
- } );
-
- contact_removed.connect( (c) => {
- contact_list_tree_view.remove_entry(c);
- ConversationWidget w = conversation_widgets[c.friend_id];
- if(w != null) {
- conversation_widgets.get(c.friend_id).destroy();
- conversation_widgets.remove(c.friend_id);
- }
- } );
- groupchat_removed.connect( (g) => {
- contact_list_tree_view.remove_entry(g);
- GroupConversationWidget w = group_conversation_widgets[g.group_id];
- if(w != null) {
- group_conversation_widgets.get(g.group_id).destroy();
- group_conversation_widgets.remove(g.group_id);
- }
- } );
-
- contact_list_tree_view.entry_activated.connect(on_entry_activated);
- contact_list_tree_view.key_press_event.connect(on_treeview_key_pressed);
- contact_list_tree_view.button_release_event.connect(
- on_treeview_button_release);
-
- //ComboboxStatus signals
- combobox_status.changed.connect(combobox_status_changed);
-
- this.focus_in_event.connect((e) => {
- this.set_urgency_hint(false);
- this.set_title(this.our_title);
- return false;
- });
-
- this.configure_event.connect((sender, event) => {
- // only save unmaximized window sizes
- if((get_window().get_state() & Gdk.WindowState.MAXIMIZED) == 0) {
- if(notebook_conversations.visible) {
- Settings.instance.window_width = event.width;
- Settings.instance.window_height = event.height;
- } else {
- Settings.instance.contactlist_width = event.width;
- Settings.instance.contactlist_height = event.height;
- }
- Settings.instance.save_settings_with_timeout(ResourceFactory.instance.config_filename);
- }
- return false;
- });
-
- label_name.label_changed.connect((str) => {
- if(str != "") {
- User.instance.name = str;
- }
- });
- label_status.label_changed.connect((str) => {
- if(str != "") {
- User.instance.status_message = str;
- }
- });
-
-#if DEBUG
- key_press_event.connect((source, key) => {
- if(key.keyval == Gdk.Key.F5) {
- init_theme();
- Logger.log(LogLevel.INFO, "Theme refreshed");
- return true;
- }
- return false;
- });
-#endif
- }
-
- private void init_save_session_hooks() {
- contact_added.connect( () => {save_session();});
- contact_removed.connect( () => {save_session();});
- groupchat_added.connect( () => {save_session();});
- groupchat_removed.connect( () => {save_session();});
- label_name.label_changed.connect( () => {save_session();});
- label_status.label_changed.connect(() => {save_session();});
- }
-
- // Restore friends from datafile
- private void init_contacts() {
- GLib.HashTable contacts = session.get_contact_list();
- contacts.foreach((key, val) => {
- Logger.log(LogLevel.INFO, "Retrieved contact %s from savefile.".printf(Tools.bin_to_hexstring(val.public_key)));
- contact_added(val);
- });
- }
-
- private void init_user() {
- User.instance.name = session.get_self_name();
- User.instance.status_message = session.get_self_status_message();
-
- label_name.label.label = User.instance.name;
- label_name.label.tooltip_text = User.instance.name;
-
- label_status.label.label = User.instance.status_message;
- label_status.label.tooltip_text = User.instance.status_message;
-
- User.instance.notify["name"].connect(() => {
- if( session.set_name(User.instance.name) ) {
- label_name.label.label = User.instance.name;
- label_name.label.tooltip_text = User.instance.name;
- } else {
- Logger.log(LogLevel.ERROR, "Could not change user name!");
- }
- });
- User.instance.notify["status-message"].connect(() => {
- if( session.set_status_message(User.instance.status_message) ) {
- label_status.label.label = User.instance.status_message;
- label_status.label.tooltip_text = User.instance.status_message;
- } else {
- Logger.log(LogLevel.ERROR, "Could not change user statusmessage!");
- }
- });
- }
-
- private bool on_treeview_button_release (Gdk.EventButton event) {
- if(event.button == Gdk.BUTTON_SECONDARY) {
- GLib.Object o = contact_list_tree_view.get_selected_entry();
- Gtk.Menu menu = null;
- if(o is Contact) {
- menu = UITools.show_contact_context_menu(this, (Contact)o);
- } else if(o is GroupChat) {
- menu = UITools.show_groupchat_context_menu(this, (GroupChat)o);
- } else {
- // empty treeview clicked
- return false;
- }
- menu.show_all();
- menu.attach_to_widget(this, null);
- menu.hide.connect(() => {menu.detach();});
- menu.popup(null, null, null, 0, 0);
- return false;
- }
- return false;
- }
-
- private void set_title_from_status(UserStatus status) {
- this.our_title = _("Venom (%s)").printf(status.to_string());
- string notify = "";
- if (this.get_urgency_hint()) {
- notify = "* ";
- }
- set_title(notify + this.our_title);
- }
-
- private void combobox_status_changed() {
- Gtk.TreeModel m = combobox_status.get_model() as Gtk.TreeModel;
- Gtk.TreeIter iter;
- combobox_status.get_active_iter(out iter);
- GLib.Value value_filter_function;
- m.get_value(iter, 1, out value_filter_function);
- ContactFilter f = value_filter_function as ContactFilter;
- Gtk.TreeModelFilter old_filter = contact_list_tree_view.get_model() as Gtk.TreeModelFilter;
- Gtk.TreeModelFilter new_filter = new Gtk.TreeModelFilter(old_filter.get_model(), null);
- new_filter.set_visible_func(f.filter_func);
- contact_list_tree_view.set_model(new_filter);
- }
-
- private void set_userstatus(UserStatus status) {
- if(user_status == status)
- return;
- if(user_status == UserStatus.OFFLINE) {
- session.start();
- image_status.hide();
- spinner_status.show();
- spinner_status.start();
- }
- session.set_user_status(status);
-
- if(status == UserStatus.OFFLINE) {
- session.stop();
- image_status.show();
- spinner_status.hide();
- spinner_status.stop();
- }
-
- user_status = status;
- }
-
- private void copy_id_to_clipboard() {
- string id_string = Tools.bin_to_hexstring(session.get_address());
- Gdk.Display display = get_display();
- Gtk.Clipboard.get_for_display(display, Gdk.SELECTION_CLIPBOARD).set_text(id_string, -1);
- Gtk.Clipboard.get_for_display(display, Gdk.SELECTION_PRIMARY).set_text(id_string, -1);
- Logger.log(LogLevel.INFO, "Copied Tox ID to clipboard");
- }
-
- private void edit_user_information() {
- UserInfoWindow w = new UserInfoWindow();
-
- w.application = application;
- w.user_name = User.instance.name;
- w.max_name_length = Tox.MAX_NAME_LENGTH;
- w.user_status = label_status.label.label;
- w.max_status_length = Tox.MAX_STATUSMESSAGE_LENGTH;
- w.user_image = image_userimage.get_pixbuf();
- w.user_id = Tools.bin_to_hexstring(session.get_address());
-
- w.set_modal(true);
- w.set_transient_for(this);
- int response = w.run();
-
- if(response == Gtk.ResponseType.APPLY) {
- //TODO once possible in core
- image_userimage.set_from_pixbuf(w.user_image);
-
- User.instance.name = w.user_name;
- User.instance.status_message = w.user_status;
- }
- w.destroy();
- }
-
- private void user_button_menu_position_function(Gtk.Menu menu, out int x, out int y, out bool push_in) {
- button_user.get_event_window().get_origin(out x, out y);
- Gtk.Allocation allocation;
- button_user.get_allocation(out allocation);
- y += allocation.height;
- push_in = true;
- }
-
- public unowned GLib.HashTable get_groupchats() {
- return session.get_groupchats();
- }
-
- private void on_outgoing_message(Message message) {
- session.on_own_message(message.to, message.message);
- session.send_message(message.to.friend_id, message.message);
- }
-
- private void on_outgoing_action(ActionMessage action) {
- session.on_own_action(action.to, action.message);
- session.send_action(action.to.friend_id, action.message);
- }
-
- private void on_outgoing_group_message(GroupMessage message) {
- session.group_message_send(message.to.group_id, message.message);
- }
- private void on_outgoing_group_action(GroupActionMessage action) {
- session.group_action_send(action.to.group_id, action.message);
- }
-
- private void on_outgoing_file(FileTransfer ft) {
- Logger.log(LogLevel.INFO, "sending file %s to %s\n".printf(ft.name,ft.friend.name));
- uint8 filenumber = session.send_file_request(ft.friend.friend_id,ft.file_size,ft.name);
- if(filenumber != -1) {
- ft.filenumber = filenumber;
- GLib.HashTable transfers = session.get_contact_list()[ft.friend.friend_id].get_filetransfers();
- transfers[filenumber] = ft;
- } else {
- Logger.log(LogLevel.ERROR, "failed to send file %s to %s".printf(ft.name, ft.friend.name));
- ft.status = FileTransferStatus.SENDING_FAILED;
- }
- }
-
- public void set_urgency () {
- if(!is_active && Settings.instance.enable_urgency_notification) {
- this.set_urgency_hint(true);
- this.set_title(_("* %s").printf(this.our_title));
- }
- }
-
- private bool on_treeview_key_pressed (Gtk.Widget source, Gdk.EventKey key) {
- if(key.keyval == Gdk.Key.Delete) {
- IContact c = contact_list_tree_view.get_selected_entry();
- if(c is Contact) {
- remove_contact(c as Contact);
- return true;
- } else if(c is GroupChat) {
- remove_groupchat(c as GroupChat);
- return true;
- }
- }
- return false;
- }
-
- // Session Signal callbacks
- private void on_friendrequest(Contact c, string message) {
- string public_key_string = Tools.bin_to_hexstring(c.public_key);
- Logger.log(LogLevel.INFO, "[fr] " + public_key_string + ":" + message);
-
- Gtk.MessageDialog message_dialog = new Gtk.MessageDialog (this,
- Gtk.DialogFlags.MODAL,
- Gtk.MessageType.QUESTION,
- Gtk.ButtonsType.NONE,
- _("New friend request from '%s'.\nDo you want to accept?"), public_key_string);
- message_dialog.add_buttons("_Cancel", Gtk.ResponseType.CANCEL, "_Accept", Gtk.ResponseType.ACCEPT, null);
- message_dialog.secondary_text = message;
- int response = message_dialog.run();
- message_dialog.destroy();
- if(response != Gtk.ResponseType.ACCEPT)
- return;
-
- int friend_add_error = session.add_friend_norequest(c);
- if(friend_add_error < 0) {
- Logger.log(LogLevel.ERROR, "Friend could not be added.");
- return;
- }
- Logger.log(LogLevel.INFO, "Added new friend #%i".printf(c.friend_id));
- contact_added(c);
- }
- private void on_typing_change(Contact c, bool is_typing) {
- if(Settings.instance.show_typing_status) {
- ConversationWidget w = open_conversation_with(c);
- w.on_typing_changed(is_typing);
- }
- }
- private void on_friendmessage(Contact c, string message) {
- Logger.log(LogLevel.DEBUG, "<%s> %s:%s".printf(new DateTime.now_local().format("%F"), c.name != null ? c.name : "<%i>".printf(c.friend_id), message));
-
- ConversationWidget w = open_conversation_with(c);
- incoming_message(new Message.incoming(c, message));
- if(notebook_conversations.get_current_page() != notebook_conversations.page_num(w)) {
- c.unread_messages++;
- contact_list_tree_view.update_entry(c);
- }
- this.set_urgency();
- }
- private void on_action(Contact c, string action) {
- Logger.log(LogLevel.DEBUG, "[ac] %i:%s".printf(c.friend_id, action));
- ConversationWidget w = open_conversation_with(c);
- incoming_action(new ActionMessage.incoming(c, action));
- if(notebook_conversations.get_current_page() != notebook_conversations.page_num(w)) {
- c.unread_messages++;
- contact_list_tree_view.update_entry(c);
- }
- this.set_urgency();
- }
- private void on_namechange(Contact c, string? old_name) {
- Logger.log(LogLevel.INFO, old_name + " changed his name to " + c.name);
- contact_changed(c);
- }
- private void on_statusmessage(Contact c, string? old_status) {
- Logger.log(LogLevel.INFO, c.name + " changed his status to " + c.status_message);
- contact_changed(c);
- }
- private void on_userstatus(Contact c, uint8 old_status) {
- Logger.log(LogLevel.INFO, "[us] %s:%i".printf(c.name, c.user_status));
- contact_changed(c);
- }
- private void on_read_receipt(Contact c, uint32 receipt) {
- Logger.log(LogLevel.INFO, "[rr] %s:%u".printf(c.name, receipt));
- }
- private void on_connectionstatus(Contact c) {
- Logger.log(LogLevel.INFO, "%s is now %s.".printf(c.name, c.online ? "online" : "offline"));
- contact_changed(c);
- }
-
- private void on_ownconnectionstatus(bool status) {
- Logger.log(LogLevel.INFO, "Connection to DHT " + (status ? "established" : "lost"));
- if(status) {
- image_status.set_tooltip_text(_("Connected to the network"));
- session.set_user_status(user_status);
- } else {
- image_status.set_tooltip_text(_("Disconnected from the network"));
- on_ownuserstatus(UserStatus.OFFLINE);
- }
- image_status.show();
- spinner_status.hide();
- spinner_status.stop();
- }
-
- private void on_ownuserstatus(UserStatus status) {
- //TODO clean up, decide what to do with deprecated GtkImageItems
- if(!session.connected || status == UserStatus.OFFLINE) {
- image_status.set_from_pixbuf(ResourceFactory.instance.offline);
- (menuitem_status.image as Gtk.Image).set_from_pixbuf(ResourceFactory.instance.offline);
- set_title_from_status(UserStatus.OFFLINE);
- return;
- }
- set_title_from_status(status);
-
- switch(status) {
- case UserStatus.ONLINE:
- image_status.set_from_pixbuf(ResourceFactory.instance.online);
- (menuitem_status.image as Gtk.Image).set_from_pixbuf(ResourceFactory.instance.online);
- break;
- case UserStatus.AWAY:
- image_status.set_from_pixbuf(ResourceFactory.instance.away);
- (menuitem_status.image as Gtk.Image).set_from_pixbuf(ResourceFactory.instance.away);
- break;
- case UserStatus.BUSY:
- image_status.set_from_pixbuf(ResourceFactory.instance.busy);
- (menuitem_status.image as Gtk.Image).set_from_pixbuf(ResourceFactory.instance.busy);
- break;
- }
- }
-
- private void on_group_invite(Contact c, GroupChat g) {
- Logger.log(LogLevel.INFO, "Group invite from %s with public key %s".printf(c.name, Tools.bin_to_hexstring(g.public_key)));
- this.set_urgency();
- Gtk.MessageDialog message_dialog = new Gtk.MessageDialog (this,
- Gtk.DialogFlags.MODAL,
- Gtk.MessageType.QUESTION,
- Gtk.ButtonsType.NONE,
- _("'%s' has invited you to a groupchat, do you want to accept?"),
- (c.name != null && c.name != "") ? c.name : Tools.bin_to_hexstring(c.public_key));
- message_dialog.add_buttons("_Cancel", Gtk.ResponseType.CANCEL, "_Accept", Gtk.ResponseType.ACCEPT, null);
-
- int response = message_dialog.run();
- message_dialog.destroy();
- if(response != Gtk.ResponseType.ACCEPT)
- return;
-
- bool ret = session.join_groupchat(c, g);
- if(ret == false) {
- Logger.log(LogLevel.ERROR, "Could not join groupchat.");
- return;
- }
- Logger.log(LogLevel.INFO, "Joined Groupchat #%i".printf(g.group_id));
- groupchat_added(g);
- }
-
- private void on_group_message(GroupChat g, int friendgroupnumber, string message) {
- string from_name = session.group_peername(g, friendgroupnumber);
- Logger.log(LogLevel.DEBUG, "[gm] %s [%i]@%i: %s".printf(from_name, friendgroupnumber, g.group_id, message));
-
- GroupConversationWidget w = open_group_conversation_with(g);
-
- //FIXME remove this workaround as soon as the problem gets fixed in the core
- /** BEGIN **/
- GroupChatContact gcc = g.peers.get(friendgroupnumber);
- if(gcc == null) {
- Logger.log(LogLevel.ERROR, "Group message from unknown contact #%i [%i]".printf(friendgroupnumber, g.group_id));
- gcc = new GroupChatContact(friendgroupnumber);
- g.peers.set(friendgroupnumber, gcc);
- on_group_peer_changed(g, friendgroupnumber, Tox.ChatChange.PEER_ADD);
- }
- /** END **/
- if(notebook_conversations.get_current_page() != notebook_conversations.page_num(w)) {
- g.unread_messages++;
- contact_list_tree_view.update_entry(g);
- }
- GroupMessage group_message = new GroupMessage.incoming(g, gcc, message);
- // only set urgency in groupchat if the message contains our name
- if(User.instance.name in message) {
- this.set_urgency();
- group_message.important = true;
- }
- incoming_group_message(group_message);
- }
-
- private void on_group_action(GroupChat g, int friendgroupnumber, string message) {
- string from_name = session.group_peername(g, friendgroupnumber);
- Logger.log(LogLevel.DEBUG, "[ga] %s [%i]@%i: %s".printf(from_name, friendgroupnumber, g.group_id, message));
-
- GroupConversationWidget w = open_group_conversation_with(g);
-
- //FIXME remove this workaround as soon as the problem gets fixed in the core
- /** BEGIN **/
- GroupChatContact gcc = g.peers.get(friendgroupnumber);
- if(gcc == null) {
- Logger.log(LogLevel.ERROR, "Group action from unknown contact #%i [%i]".printf(friendgroupnumber, g.group_id));
- gcc = new GroupChatContact(friendgroupnumber);
- g.peers.set(friendgroupnumber, gcc);
- on_group_peer_changed(g, friendgroupnumber, Tox.ChatChange.PEER_ADD);
- }
- /** END **/
-
- if(notebook_conversations.get_current_page() != notebook_conversations.page_num(w)) {
- g.unread_messages++;
- contact_list_tree_view.update_entry(g);
- }
- GroupActionMessage group_message = new GroupActionMessage.incoming(g, gcc, message);
- // only set urgency in groupchat if the message contains our name
- if(User.instance.name in message) {
- this.set_urgency();
- group_message.important = true;
- }
- incoming_group_action(group_message);
- }
-
- private void on_group_peer_changed(GroupChat g, int peernumber, Tox.ChatChange change) {
- GroupConversationWidget w = open_group_conversation_with(g);
- w.update_contact(peernumber, change);
- groupchat_changed(g);
- }
-
- private void on_file_sendrequest(int friendnumber, uint8 filenumber, uint64 filesize,string filename) {
- Logger.log(LogLevel.INFO, "received file send request friend: %i filenumber: %i filename: %s ".printf(friendnumber, filenumber, filename));
- Contact contact = session.get_contact_list()[friendnumber];
- FileTransfer ft;
- if((filename.has_suffix(".png") || filename.has_suffix(".jpg") || filename.has_suffix(".jpeg")) && filesize <= 0x100000) {
- ft = new FileTransfer.recvdata(contact, filename, filesize);
- } else {
- ft = new FileTransfer(contact, FileTransferDirection.INCOMING, filesize, filename, null);
- }
-
- ft.filenumber = filenumber;
- GLib.HashTable transfers = session.get_contact_list()[friendnumber].get_filetransfers();
- transfers[filenumber] = ft;
- ConversationWidget w = conversation_widgets[friendnumber];
- w.on_incoming_filetransfer(ft);
-
- if(!ft.isfile) {
- session.accept_file(friendnumber, filenumber);
- ft.status = FileTransferStatus.IN_PROGRESS;
- }
-
- this.set_urgency();
- }
-
- private void send_file(int friendnumber, uint8 filenumber) {
- int chunk_size = session.get_recommended_data_size(friendnumber);
- FileTransfer ft = session.get_contact_list()[friendnumber].get_filetransfers()[filenumber];
- ft.status = FileTransferStatus.IN_PROGRESS;
- if(ft == null) {
- Logger.log(LogLevel.ERROR, "Trying to send unknown file");
- return;
- }
-
- GLib.FileInputStream file_stream = null;
- File file = null;
-
- if(ft.isfile) {
- file = File.new_for_path(ft.path);
- }
-
- try {
- uint64 file_size;
-
- if(ft.isfile) {
- file_stream = file.read();
- var file_info = file.query_info ("*", FileQueryInfoFlags.NONE);
- file_size = file_info.get_size();
- } else {
- file_size = ft.file_size;
- }
-
- uint64 remaining_bytes_to_send = file_size - ft.bytes_processed;
- uint8[] bytes = new uint8[chunk_size];
- bool read_more = true;
- while ( remaining_bytes_to_send > 0 ) {
- if(ft.status == FileTransferStatus.SENDING_FAILED || ft.status == FileTransferStatus.CANCELED
- || ft.status == FileTransferStatus.SENDING_BROKEN) {
- return;
- }
- if(ft.status == FileTransferStatus.PAUSED) {
- Thread.usleep(1000);
- continue;
- }
-
- if(remaining_bytes_to_send < chunk_size) {
- chunk_size = (int) remaining_bytes_to_send;
- bytes = new uint8[chunk_size];
- }
- if(read_more) {
- if(ft.isfile) {
- size_t res = file_stream.read(bytes);
- if(res != chunk_size) {
- Logger.log(LogLevel.ERROR, "Read incorrect number of bytes from file");
- }
- } else {
- Memory.copy(bytes, (uint8*)ft.data + ft.bytes_processed, chunk_size);
- }
- }
- int res = session.send_file_data(friendnumber,filenumber,bytes);
- if(res != -1) {
- remaining_bytes_to_send -= chunk_size;
- ft.bytes_processed += chunk_size;
- read_more = true;
- } else {
- read_more = false;
- Thread.usleep(1000);
- }
- }
- session.send_filetransfer_end(friendnumber,filenumber);
- ft.status = FileTransferStatus.DONE;
- } catch(IOError e) {
- Logger.log(LogLevel.ERROR, "I/O error while trying to read file: " + e.message);
- } catch(Error e) {
- Logger.log(LogLevel.ERROR, "Unknown error while trying to read file: " + e.message);
- } finally {
- try {
- if(file_stream != null)
- file_stream.close();
- } catch(IOError e) {
- Logger.log(LogLevel.ERROR, "I/O error while trying to close file stream: " + e.message);
- }
- }
- Logger.log(LogLevel.INFO, "Ended file transfer for %s to %s".printf(ft.name, (session.get_contact_list()[friendnumber]).name));
- }
-
- private void on_file_control_request(int friendnumber,uint8 filenumber,uint8 receive_send,uint8 status, uint8[] data) {
- FileTransfer ft = session.get_contact_list()[friendnumber].get_filetransfers()[filenumber];
- if(ft == null)
- return;
- if(status == Tox.FileControlStatus.ACCEPT && receive_send == 1) {
- Logger.log(LogLevel.INFO, "Contact accepted file sending request");
- new Thread(null, () => {
- send_file(friendnumber,filenumber);return true;
- });
- }
-
- if(status == Tox.FileControlStatus.ACCEPT && receive_send == 0) {
- ft.status = FileTransferStatus.IN_PROGRESS;
- }
-
- if(status == Tox.FileControlStatus.KILL && receive_send == 1) {
- if(ft.status == FileTransferStatus.PENDING) {
- ft.status = FileTransferStatus.REJECTED;
- } else if(ft.direction == FileTransferDirection.OUTGOING) {
- ft.status = FileTransferStatus.SENDING_FAILED;
- } else if(ft.direction == FileTransferDirection.INCOMING) {
- ft.status = FileTransferStatus.RECEIVING_FAILED;
- }
- Logger.log(LogLevel.INFO, "File transfer was rejected for file number %u".printf(filenumber));
- }
- if(status == Tox.FileControlStatus.FINISHED && receive_send == 0) {
- ft.status = FileTransferStatus.DONE;
- Logger.log(LogLevel.INFO, "File transfer finished for file number %u".printf(filenumber));
- }
-
- if(status == Tox.FileControlStatus.RESUME_BROKEN && receive_send == 1) {
- ft.bytes_processed = ((uint64[])data)[0];
- ft.status = FileTransferStatus.IN_PROGRESS;
- session.accept_file_resume(friendnumber, filenumber);
- new Thread(null, () => {
- send_file(friendnumber,filenumber);return true;
- });
- }
- }
-
- private void on_file_data(int friendnumber,uint8 filenumber,uint8[] data) {
- FileTransfer ft = session.get_contact_list()[friendnumber].get_filetransfers()[filenumber];
- if(ft == null) {
- session.reject_file(friendnumber,filenumber);
- return;
- }
-
- if(ft.isfile) {
- string path = ft.path;
- File file = File.new_for_path(path);
- try{
- if(!file.query_exists())
- file.create(FileCreateFlags.NONE);
- FileOutputStream fos = file.append_to(FileCreateFlags.NONE);
- size_t bytes_written;
- fos.write_all(data,out bytes_written);
- ft.bytes_processed += bytes_written;
- fos.close();
- } catch (Error e){
- Logger.log(LogLevel.ERROR, "Error while trying to write data to file");
- ft.status = FileTransferStatus.RECEIVING_FAILED;
- }
- } else {
- ByteArray buffer = new ByteArray.take(ft.data);
- buffer.append(data);
- ft.data = buffer.data;
- ft.bytes_processed += data.length;
- }
-
- }
-
- private ConversationWidget? open_conversation_with(Contact c) {
- ConversationWidget w = conversation_widgets[c.friend_id];
- if(w == null) {
- w = new ConversationWidget(c);
- w.load_history(session.load_history_for_contact(c));
- incoming_message.connect(w.on_incoming_message);
- incoming_action.connect(w.on_incoming_message);
- w.new_outgoing_message.connect(on_outgoing_message);
- w.new_outgoing_action.connect(on_outgoing_action);
- w.new_outgoing_file.connect(on_outgoing_file);
- w.typing_status.connect( (is_typing) => {
- if(Settings.instance.send_typing_status) {
- session.set_user_is_typing(c.friend_id, is_typing);
- }
- });
- w.filetransfer_accepted.connect ( (ft) => {
- session.accept_file(ft.friend.friend_id,ft.filenumber);
- });
- w.filetransfer_rejected.connect ( (ft) => {
- session.reject_file(ft.friend.friend_id,ft.filenumber);
- });
- w.contact_changed.connect((contact) => {contact_changed(contact);});
- conversation_widgets[c.friend_id] = w;
- notebook_conversations.append_page(w, null);
- }
- w.show_all();
- return w;
- }
- private GroupConversationWidget? open_group_conversation_with(GroupChat g) {
- GroupConversationWidget w = group_conversation_widgets[g.group_id];
- if(w == null) {
- w = new GroupConversationWidget(g);
- incoming_group_message.connect(w.on_incoming_message);
- incoming_group_action.connect(w.on_incoming_message);
- w.new_outgoing_message.connect(on_outgoing_group_message);
- w.new_outgoing_action.connect(on_outgoing_group_action);
- w.groupchat_changed.connect((groupchat) => {groupchat_changed(groupchat);});
- group_conversation_widgets[g.group_id] = w;
- notebook_conversations.append_page(w, null);
- }
- w.show_all();
- return w;
- }
-
- // Contact doubleclicked in treeview
- private void on_entry_activated(IContact ic) {
- Gtk.Widget conversation_widget = null;
- if(ic is Contact) {
- Contact c = ic as Contact;
- conversation_widget = open_conversation_with(c);
-
- if(c.unread_messages != 0) {
- c.unread_messages = 0;
- contact_list_tree_view.update_entry(c);
- }
- } else if(ic is GroupChat) {
- GroupChat g = ic as GroupChat;
- conversation_widget = open_group_conversation_with(g);
-
- if(g.unread_messages != 0) {
- g.unread_messages = 0;
- contact_list_tree_view.update_entry(g);
- }
- } else {
- GLib.assert_not_reached();
- }
- int current_page = notebook_conversations.page_num(conversation_widget);
- notebook_conversations.set_current_page(current_page);
- if(notebook_conversations.visible == false) {
- notebook_conversations.visible = true;
- resize(Settings.instance.window_width, Settings.instance.window_height);
- }
- }
-
- public void remove_contact(Contact c) {
- if(c == null)
- return;
- string name;
- if(c.name != null && c.name != "") {
- name = c.name;
- } else {
- name = Tools.bin_to_hexstring(c.public_key);
- }
- Gtk.MessageDialog message_dialog = new Gtk.MessageDialog (this,
- Gtk.DialogFlags.MODAL,
- Gtk.MessageType.WARNING,
- Gtk.ButtonsType.NONE,
- _("Are you sure you want to delete '%s' from your contact list?"), name);
- message_dialog.add_buttons("_Cancel", Gtk.ResponseType.CANCEL, "_Delete", Gtk.ResponseType.OK, null);
- int response = message_dialog.run();
- message_dialog.destroy();
- if(response != Gtk.ResponseType.OK)
- return;
-
- if(!session.del_friend(c)) {
- Logger.log(LogLevel.ERROR, "Could not remove " + name);
- return;
- }
- contact_removed(c);
- }
-
- public void invite_to_groupchat(Contact c, int groupchat_number = -1) {
- GroupChat g = null;
- if(groupchat_number < 0) {
- g = session.add_groupchat();
- if(g == null) {
- Logger.log(LogLevel.ERROR, "Could not create a new groupchat.");
- return;
- }
- groupchat_added(g);
- } else {
- g = get_groupchats().get(groupchat_number);
- }
- session.invite_friend(c, g);
- }
-
- public void remove_groupchat(GroupChat g) {
- if(g == null)
- return;
- string name = _("groupchat #%i").printf(g.group_id);
- Gtk.MessageDialog message_dialog = new Gtk.MessageDialog (this,
- Gtk.DialogFlags.MODAL,
- Gtk.MessageType.WARNING,
- Gtk.ButtonsType.NONE,
- _("Are you sure you want to delete '%s' from your contact list?"), name);
- message_dialog.add_buttons("_Cancel", Gtk.ResponseType.CANCEL, "_Delete", Gtk.ResponseType.OK, null);
- int response = message_dialog.run();
- message_dialog.destroy();
- if(response != Gtk.ResponseType.OK)
- return;
-
- if(!session.del_groupchat(g)) {
- Logger.log(LogLevel.ERROR, "Could not remove " + name);
- return;
- }
- groupchat_removed(g);
- }
-
- private bool add_contact_real(string contact_id_string, string contact_message = "", string contact_alias = "") {
- string stripped_id = Tools.remove_whitespace(contact_id_string);
- string alias = contact_alias;
-
- // Try to resolve the tox id from an address if the size does not match
- if(stripped_id.length != Tox.FRIEND_ADDRESS_SIZE * 2) {
- if (ToxDns.tox_uri_regex != null && ToxDns.tox_uri_regex.match(stripped_id)) {
- ToxDns dns_resolver = new ToxDns();
- dns_resolver.default_host = Settings.instance.default_host;
- string resolved_id = dns_resolver.resolve_id(stripped_id, open_get_pin_dialog);
- if(alias == "") {
- alias = dns_resolver.authority_user;
- }
- if(resolved_id != null) {
- stripped_id = resolved_id;
- } else {
- Logger.log(LogLevel.ERROR, "Could not resolve ID from DNS record");
- UITools.show_error_dialog(_("Resolving ID failed"), _("Could not resolve ID from DNS record\n"), this);
- return false;
- }
- }
- }
-
- uint8[] contact_id = Tools.hexstring_to_bin(stripped_id);
- // add friend
- if(contact_id == null || contact_id.length != Tox.FRIEND_ADDRESS_SIZE) {
- Logger.log(LogLevel.INFO, "Could not add friend: Invalid ID");
- UITools.show_error_dialog(_("Adding Friend failed"), _("Could not add friend: Invalid ID\n"), this);
- return false;
- }
- Contact c = new Contact(contact_id);
- Logger.log(LogLevel.INFO, "setting alias: " + alias);
- if(alias != "") {
- c.alias = alias;
- }
- Tox.FriendAddError ret = session.add_friend(c, contact_message);
- if(ret < 0) {
- Logger.log(LogLevel.ERROR, "Could not add friend: %s.".printf(Tools.friend_add_error_to_string(ret)));
- UITools.show_error_dialog(_("Adding Friend failed"), _("Could not add friend: %s.\n").printf(Tools.friend_add_error_to_string(ret)), this);
- return false;
- }
-
- session.save_extended_contact_data(c);
- Logger.log(LogLevel.INFO, "Friend request successfully sent. Friend added as %i.".printf((int)ret));
- contact_added(c);
- return true;
- }
-
- private string? open_get_pin_dialog(string? username) {
- string pin = "";
- PinDialog dialog = new PinDialog( username );
- dialog.transient_for = this;
- dialog.modal = true;
- dialog.show_all();
-
- int result = dialog.run();
- if(result == Gtk.ResponseType.OK) {
- pin = dialog.pin;
- }
- dialog.destroy();
- return pin;
- }
-
- public void add_contact(string? contact_id = null, string? contact_message = null) {
- AddContactDialog dialog = new AddContactDialog();
- if(contact_id != null) {
- dialog.id = contact_id;
- }
- if(contact_message != null) {
- dialog.message = contact_message;
- }
- dialog.set_transient_for(this);
-
- string contact_id_string = "";
- string contact_alias = "";
- string contact_message_string = "";
- int response = Gtk.ResponseType.CANCEL;
- do {
- response = dialog.run();
- contact_id_string = dialog.id;
- contact_alias = dialog.contact_alias;
- contact_message_string = dialog.message;
- } while(response == Gtk.ResponseType.OK && !add_contact_real(contact_id_string, contact_message_string, contact_alias));
-
- dialog.destroy();
- }
-
- public void button_group_chat_clicked(Gtk.Button source) {
- GroupChat g = session.add_groupchat();
- if(g == null) {
- Logger.log(LogLevel.ERROR, "Could not create a new groupchat.");
- return;
- }
- groupchat_added(g);
- }
- }
-}
diff --git a/src/ui/ConversationTextView.vala b/src/ui/ConversationTextView.vala
deleted file mode 100644
index 9fecfe2..0000000
--- a/src/ui/ConversationTextView.vala
+++ /dev/null
@@ -1,327 +0,0 @@
-/*
- * ConversationTextView.vala
- *
- * Copyright (C) 2014 Venom authors and contributors
- *
- * This file is part of Venom.
- *
- * Venom is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * Venom is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with Venom. If not, see .
- */
-
-namespace Venom {
- public class ConversationTextView : IConversationView, Gtk.TextView {
- public bool short_names {get; set; default = false;}
- public string is_typing_string {get; set; default = "";}
-
- private Gtk.TextTag bold_tag;
- private Gtk.TextTag grey_tag;
- private Gtk.TextTag important_tag;
- private Gtk.TextTag italic_tag;
- private Gtk.TextTag quotation_tag;
-
- private bool is_typing_status = false;
- private Gtk.TextIter typing_status_iter;
-
- public ConversationTextView() {
- this.get_style_context().add_class("conversation_view");
- set_wrap_mode(Gtk.WrapMode.WORD_CHAR);
- editable = false;
-
- bold_tag = buffer.create_tag(null, "weight", 600);
- grey_tag = buffer.create_tag(null, "foreground", "grey");
- important_tag = buffer.create_tag(null,
- "weight", 600,
- "foreground", "white",
- "background", "darkgrey"
- );
- italic_tag = buffer.create_tag(null, "style", Pango.Style.ITALIC);
- quotation_tag = buffer.create_tag(null, "foreground", "green");
- key_press_event.connect((e) => {
- switch(e.keyval) {
- case Gdk.Key.Return:
- case Gdk.Key.KP_Enter:
- Gtk.TextIter iter;
- buffer.get_iter_at_mark(out iter, buffer.get_insert());
- activate_uri_at_iter(iter);
- break;
- default:
- break;
- }
- return false;
- });
- event_after.connect((e) => {
- if(e.type != Gdk.EventType.BUTTON_RELEASE)
- return;
- Gtk.TextIter start, end, iter;
-
- // Don't activate on selection
- buffer.get_selection_bounds(out start, out end);
- if(start.get_offset() != end.get_offset())
- return;
- int x, y;
- window_to_buffer_coords(Gtk.TextWindowType.WIDGET, (int)e.button.x, (int)e.button.y, out x, out y);
- get_iter_at_location(out iter, x, y);
- activate_uri_at_iter(iter);
- });
- bool hovering = false;
- Gdk.Cursor hand_cursor = new Gdk.Cursor(Gdk.CursorType.HAND1);
- Gdk.Cursor regular_cursor = new Gdk.Cursor(Gdk.CursorType.XTERM);
- motion_notify_event.connect((e)=> {
- int x, y;
- window_to_buffer_coords(Gtk.TextWindowType.WIDGET, (int)e.x, (int)e.y, out x, out y);
- Gtk.TextIter iter;
- get_iter_at_location(out iter, x, y);
- if(get_uri_at_iter(iter) != null) {
- if(!hovering) {
- hovering = true;
- this.get_window(Gtk.TextWindowType.TEXT).set_cursor(hand_cursor);
- }
- } else {
- if(hovering) {
- hovering = false;
- this.get_window(Gtk.TextWindowType.TEXT).set_cursor(regular_cursor);
- }
- }
- return false;
- });
- this.notify["is-typing-string"].connect(() => {
- remove_typing_status();
- append_typing_status();
- });
- }
-
- public void on_typing_changed(bool status) {
- if(status && !is_typing_status) {
- is_typing_status = status;
- append_typing_status();
- } else if (!status && is_typing_status) {
- remove_typing_status();
- is_typing_status = status;
- }
- }
-
- private void remove_typing_status() {
- if(!is_typing_status) {
- return;
- }
- Gtk.TextIter text_end;
- buffer.get_end_iter(out text_end);
- buffer.delete(ref typing_status_iter, ref text_end);
- }
-
- private void append_typing_status() {
- if(!is_typing_status) {
- return;
- }
- buffer.get_end_iter(out typing_status_iter);
- buffer.insert_with_tags(typing_status_iter, is_typing_string, is_typing_string.length, italic_tag);
- buffer.get_end_iter(out typing_status_iter);
- typing_status_iter.backward_chars(is_typing_string.length);
- }
-
- public void add_message(IMessage message) {
- remove_typing_status();
-
- Gtk.TextIter text_end;
- string text;
- buffer.get_end_iter(out text_end);
- text = _("[%s] ").printf(
- message.get_time_plain()
- );
- buffer.insert_with_tags(text_end, text, text.length, grey_tag);
-
- buffer.get_end_iter(out text_end);
- if(short_names) {
- text = Tools.shorten_name(message.get_sender_plain());
- } else {
- text = message.get_sender_plain();
- }
-
- if(message.important) {
- buffer.insert_with_tags(text_end, text, text.length, important_tag);
- } else {
- buffer.insert_with_tags(text_end, text, text.length, bold_tag);
- }
-
- buffer.get_end_iter(out text_end);
- text = ": ";
- buffer.insert_with_tags(text_end, text, text.length, bold_tag);
-
- buffer.get_end_iter(out text_end);
- text = message.get_message_plain();
- if (text[0] == '>') {
- buffer.insert_with_tags(text_end, text, text.length, quotation_tag);
- } else {
- GLib.MatchInfo match_info;
- Tools.uri_regex.match(text, 0, out match_info);
- int start = 0, end = 0, offset = 0;
- while(match_info.matches() && match_info.fetch_pos(0, out start, out end)) {
- // Add preceding text
- if(start > offset) {
- buffer.insert(ref text_end, text[offset:start], offset - start);
- }
- // Add uri
- string uri = match_info.fetch(0);
- insert_uri(text_end, uri);
-
- buffer.get_end_iter(out text_end);
- offset = end;
-
- try {
- match_info.next();
- } catch (GLib.RegexError e) {
- Logger.log(LogLevel.ERROR, "Error matching uri regex: " + e.message);
- break;
- }
- }
- // Add trailing text
- if(text.length > offset) {
- string after = text.substring(offset);
- buffer.insert(ref text_end, after, -1);
- }
- }
-
- buffer.get_end_iter(out text_end);
- buffer.insert(ref text_end, "\n", 1);
-
- append_typing_status();
- }
-
- public void add_filetransfer(FileTransferChatEntry entry) {
- remove_typing_status();
-
- Gtk.TextIter iter;
- buffer.get_end_iter(out iter);
- Gtk.TextChildAnchor child_anchor = buffer.create_child_anchor(iter);
- add_child_at_anchor(entry, child_anchor);
- entry.show();
-
- buffer.get_end_iter(out iter);
- buffer.insert(ref iter, "\n", 1);
-
- append_typing_status();
- }
-
- private void insert_uri(Gtk.TextIter iter, string uri) {
- Gtk.TextTag uri_tag;
- uri_tag = buffer.create_tag(null,
- "underline", Pango.Underline.SINGLE,
- "foreground", "blue"
- );
- uri_tag.set_data("uri", uri);
- buffer.insert_with_tags(iter, uri, uri.length, uri_tag);
- }
-
- private string? get_uri_at_iter(Gtk.TextIter iter) {
- GLib.SList tags = iter.get_tags();
- for(unowned GLib.SList tagp = tags; tagp != null; tagp = tagp.next) {
- var tag = tagp.data;
- string uri = tag.get_data("uri");
- if(uri != null) {
- return uri;
- }
- }
- return null;
- }
-
- private void activate_uri_at_iter(Gtk.TextIter iter) {
- string uri = get_uri_at_iter(iter);
- if(uri == null)
- return;
- try {
- Gtk.show_uri(null, uri, 0);
- } catch (Error e) {
- Logger.log(LogLevel.ERROR, "Error when showing uri: " + e.message);
- }
- }
-
- private bool forward_search(Gtk.TextIter iter, string text, Gtk.TextIter? limit = null, bool match_case = false) {
- Gtk.TextIter match_start;
- Gtk.TextIter match_end;
- bool found = iter.forward_search(text, match_case ? 0 : Gtk.TextSearchFlags.CASE_INSENSITIVE , out match_start, out match_end, limit);
- if(found) {
- scroll_to_iter(match_start, 0, false, 0, 0);
- buffer.select_range(match_start, match_end);
- }
- return found;
- }
-
- private void search(string search_text, bool wrap_around = true, bool match_case = false) {
- Gtk.TextIter current_position_iter;
- buffer.get_iter_at_mark(out current_position_iter, buffer.get_insert());
- if(!forward_search(current_position_iter, search_text, null) && wrap_around) {
- Gtk.TextIter start_iter;
- buffer.get_start_iter(out start_iter);
- forward_search(start_iter, search_text, current_position_iter);
- }
- }
-
- public void register_search_entry(Gtk.Entry entry) {
- key_press_event.connect((k) => {
- if(k.keyval == Gdk.Key.f && (k.state & Gdk.ModifierType.CONTROL_MASK) != 0) {
- entry.show();
- entry.grab_focus();
- return true;
- }
- return false;
- });
-
- entry.key_press_event.connect((k) => {
- if(k.keyval == Gdk.Key.Escape) {
- entry.hide();
- grab_focus();
- return true;
- }
- return false;
- });
-
- bool match_case = false;
- bool wrap_around = true;
-
- bool hold_searchbar = false;
-
- entry.icon_release.connect((p0, p1) => {
- if(p1.button.button == 3) {
- hold_searchbar = true;
- Gtk.Menu menu = new Gtk.Menu();
-
- Gtk.CheckMenuItem menu_item_case = new Gtk.CheckMenuItem.with_mnemonic("_Match case");
- menu_item_case.active = match_case;
- menu_item_case.toggled.connect(() => { match_case = menu_item_case.active; });
- menu.append(menu_item_case);
-
- Gtk.CheckMenuItem menu_item_wrap = new Gtk.CheckMenuItem.with_mnemonic("_Wrap around");
- menu_item_wrap.active = wrap_around;
- menu_item_wrap.toggled.connect(() => { wrap_around = menu_item_wrap.active; });
- menu.append(menu_item_wrap);
-
- menu.show_all();
- menu.attach_to_widget(entry, null);
- menu.hide.connect(() => {hold_searchbar = false; menu.detach();});
- menu.popup(null, null, null, 0, 0);
- }
- });
-
- entry.focus_out_event.connect(() => {
- if(!hold_searchbar)
- entry.hide();
- return false;
- });
-
- entry.insert_text.connect( (new_text, new_text_length, ref position) => {
- search(entry.text + new_text, wrap_around, match_case);
- });
- }
- }
-}
diff --git a/src/ui/ConversationView.vala b/src/ui/ConversationView.vala
deleted file mode 100644
index cf69c83..0000000
--- a/src/ui/ConversationView.vala
+++ /dev/null
@@ -1,110 +0,0 @@
-/*
- * ConversationView.vala
- *
- * Copyright (C) 2013-2014 Venom authors and contributors
- *
- * This file is part of Venom.
- *
- * Venom is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * Venom is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with Venom. If not, see .
- */
-
-namespace Venom {
- public interface IConversationView : Gtk.Widget {
- public abstract bool short_names {get; set;}
- public abstract string is_typing_string {get; set;}
- public abstract void add_message(IMessage message);
- public abstract void add_filetransfer(FileTransferChatEntry entry);
- public abstract void register_search_entry(Gtk.Entry entry);
- public abstract void on_typing_changed(bool status);
- }
-
- public class ConversationView : IConversationView, Gtk.EventBox {
- public bool short_names {get; set; default = false;}
- public string is_typing_string {get; set; default = "";}
- private Gtk.Box conversation_list;
- private Gtk.Label is_typing_label;
- private IMessage last_message = null;
- private int last_width;
-
- public void on_typing_changed(bool status) {
- is_typing_label.visible = status;
- }
-
- public ConversationView() {
- conversation_list = new Gtk.Box(Gtk.Orientation.VERTICAL, 3);
- this.get_style_context().add_class("conversation_view");
- this.add(conversation_list);
-
- is_typing_label = new Gtk.Label(is_typing_string);
- is_typing_label.xalign = 0;
- is_typing_label.no_show_all = true;
- is_typing_label.visible = false;
- is_typing_label.set_use_markup(true);
- this.notify["is-typing-string"].connect(() => {
- is_typing_label.set_markup(_("%s").printf(is_typing_string));
- });
- conversation_list.pack_end(is_typing_label, false, false);
- }
-
- public void add_filetransfer(FileTransferChatEntry entry) {
- entry.filetransfer_completed.connect((entry, ft) => {
- if(!ft.isfile) {
- try {
- Gdk.PixbufLoader loader = new Gdk.PixbufLoader();
- loader.write(ft.data);
- loader.close();
-
- int position;
- conversation_list.child_get(entry, "position", out position);
-
- Gtk.Image image = new Gtk.Image.from_pixbuf(loader.get_pixbuf());
- conversation_list.pack_start(image, false, false, 0);
- conversation_list.reorder_child(image, position + 1);
- image.set_alignment(0, 0);
- image.set_visible(true);
-
- } catch (Error error) {
- Logger.log(LogLevel.ERROR, "Adding filetransfer failed: " + error.message);
- }
- }
- });
-
- conversation_list.pack_start(entry, false, false, 0);
- entry.set_visible(true);
-
- last_message = null;
- }
-
- public void add_message(IMessage message) {
- bool same_sender = false;
- ChatMessage cm;
-
- if(last_message != null && last_message.compare_sender(message)) {
- same_sender = true;
- }
-
- cm = new ChatMessage(message, short_names, same_sender, last_width);
-
- conversation_list.pack_start(cm, false, false);
- cm.show_all();
-
- if(!same_sender) {
- last_width = cm.get_name_label_width();
- }
- last_message = message;
- }
- public void register_search_entry(Gtk.Entry entry) {
- }
- }
-}
diff --git a/src/ui/ConversationWidget.vala b/src/ui/ConversationWidget.vala
deleted file mode 100644
index 2cc3979..0000000
--- a/src/ui/ConversationWidget.vala
+++ /dev/null
@@ -1,327 +0,0 @@
-/*
- * ConversationWidget.vala
- *
- * Copyright (C) 2013-2014 Venom authors and contributors
- *
- * This file is part of Venom.
- *
- * Venom is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * Venom is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with Venom. If not, see .
- */
-
-namespace Venom {
- public class ConversationWidget : Gtk.EventBox {
- private EditableLabel label_contact_name;
- private Gtk.Label label_contact_statusmessage;
- private Gtk.Image image_contact_image;
- private Gtk.Button button_send;
- private Gtk.Button button_send_file;
-
- private MessageTextView message_textview;
- private IConversationView conversation_view;
- public unowned Contact contact {get; private set;}
-
- public signal void new_outgoing_message(Message message);
- public signal void new_outgoing_action(ActionMessage action);
- public signal void new_outgoing_file(FileTransfer ft);
- public signal void typing_status(bool typing);
- public signal void filetransfer_accepted(FileTransfer ft);
- public signal void filetransfer_rejected(FileTransfer ft);
- public signal void contact_changed(Contact c);
-
- public ConversationWidget( Contact contact ) {
- this.contact = contact;
- init_widgets();
- setup_drag_drop();
- update_contact();
- }
-
- public void update_contact() {
- // update contact name
- label_contact_name.label.label = _("%s").printf(contact.get_name_string_with_hyperlinks());
-
- // update contact status message
- label_contact_statusmessage.label = contact.get_status_string_with_hyperlinks();
-
- // update contact image
- image_contact_image.set_from_pixbuf(contact.image != null ? contact.image : ResourceFactory.instance.default_contact);
-
- if( contact.name != null )
- conversation_view.is_typing_string = _("%s is typing...").printf(Markup.escape_text(contact.name));
-
- button_send_file.sensitive = contact.online;
- button_send.sensitive = contact.online;
-
- // remove is_typing notification for offline contacts
- if(!contact.online){
- on_typing_changed(false);
- }
- }
-
- private void init_widgets() {
- Gtk.Builder builder = new Gtk.Builder();
- try {
- builder.add_from_resource("/org/gtk/venom/conversation_window.ui");
- } catch (GLib.Error e) {
- Logger.log(LogLevel.FATAL, "Loading conversation window failed: " + e.message);
- }
- Gtk.Box box = builder.get_object("box") as Gtk.Box;
- this.add(box);
- this.get_style_context().add_class("conversation_widget");
- label_contact_statusmessage = builder.get_object("label_contact_statusmessage") as Gtk.Label;
- image_contact_image = builder.get_object("image_contact_image") as Gtk.Image;
-
- Gtk.Image image_send = builder.get_object("image_send") as Gtk.Image;
- Gtk.Image image_call = builder.get_object("image_call") as Gtk.Image;
- Gtk.Image image_call_video = builder.get_object("image_call_video") as Gtk.Image;
-
- Gtk.Image image_send_file = builder.get_object("image_send_file") as Gtk.Image;
- Gtk.Image image_insert_smiley = builder.get_object("image_insert_smiley") as Gtk.Image;
-
- Gtk.Label label_contact_name_ = builder.get_object("label_contact_name") as Gtk.Label;
- Gtk.Box box_user_info = builder.get_object("box_user_info") as Gtk.Box;
- box_user_info.remove(label_contact_name_);
- label_contact_name = new EditableLabel.with_label(label_contact_name_);
- box_user_info.pack_start(label_contact_name, false);
- label_contact_name.button_cancel.get_style_context().add_class("callbutton");
- label_contact_name.button_ok.get_style_context().add_class("callbutton");
- label_contact_name.show_all();
- label_contact_name.show_entry.connect_after(() => {
- label_contact_name.entry.text = contact.alias;
- });
- label_contact_name.label_changed.connect((new_alias) => {
- contact.alias = new_alias;
- contact_changed(contact);
- });
-
- //TODO
- //Gtk.Button button_call = builder.get_object("button_call") as Gtk.Button;
- //Gtk.Button button_call_video = builder.get_object("button_call_video") as Gtk.Button;
- button_send = builder.get_object("button_send") as Gtk.Button;
- button_send_file = builder.get_object("button_send_file") as Gtk.Button;
-
- button_send.clicked.connect(() => {textview_activate();});
- button_send_file.clicked.connect(button_send_file_clicked);
-
- Gtk.ScrolledWindow scrolled_window_message = builder.get_object("scrolled_window_message") as Gtk.ScrolledWindow;
- message_textview = new MessageTextView();
- message_textview.border_width = 6;
- message_textview.wrap_mode = Gtk.WrapMode.WORD_CHAR;
- message_textview.textview_activate.connect(textview_activate);
- message_textview.typing_status.connect((is_typing) => {
- typing_status(is_typing);
- });
-
- message_textview.paste_clipboard.connect(() => {
- Gtk.Clipboard cb = Gtk.Clipboard.get(Gdk.SELECTION_CLIPBOARD);
- if(cb.wait_is_image_available()) {
- Gdk.Pixbuf pb = cb.wait_for_image();
- try {
- uint8[] data;
- pb.save_to_buffer(out data, "png");
- if(data.length > 0x100000) {
- pb.save_to_buffer(out data, "jpeg");
- prepare_send_data("clipboard.jpg", data);
- } else {
- prepare_send_data("clipboard.png", data);
- }
-
- } catch (Error error) {
- }
- }
- });
-
- scrolled_window_message.add(message_textview);
-
- image_send.set_from_pixbuf(ResourceFactory.instance.send);
- image_call.set_from_pixbuf(ResourceFactory.instance.call);
- image_call_video.set_from_pixbuf(ResourceFactory.instance.call_video);
- image_send_file.set_from_pixbuf(ResourceFactory.instance.send_file);
- image_insert_smiley.set_from_pixbuf(ResourceFactory.instance.smiley);
-
-
- Gtk.ScrolledWindow scrolled_window = builder.get_object("scrolled_window") as Gtk.ScrolledWindow;
-
- if( ResourceFactory.instance.textview_mode ) {
- conversation_view = new ConversationTextView();
- scrolled_window.add(conversation_view);
- } else {
- conversation_view = new ConversationView();
- scrolled_window.add_with_viewport(conversation_view);
- }
- conversation_view.get_style_context().add_class("chat_list");
- conversation_view.short_names = true;
-
- Gtk.Overlay overlay = builder.get_object("overlay") as Gtk.Overlay;
- Gtk.Entry entry_search = new SearchEntry();
- entry_search.halign = Gtk.Align.END;
- entry_search.valign = Gtk.Align.START;
- entry_search.no_show_all = true;
- conversation_view.register_search_entry(entry_search);
- overlay.add_overlay(entry_search);
-
- Gtk.Adjustment vadjustment = scrolled_window.get_vadjustment();
- bool scroll_to_bottom = true;
- conversation_view.size_allocate.connect( () => {
- if(scroll_to_bottom) {
- vadjustment.value = vadjustment.upper - vadjustment.page_size;
- }
- });
- vadjustment.value_changed.connect( () => {
- scroll_to_bottom = (vadjustment.value == vadjustment.upper - vadjustment.page_size);
- });
-
- delete_event.connect(hide_on_delete);
- }
-
- bool is_typing = false;
- // changes typing status to false after >= 15 seconds of inactivity
- bool is_typing_timeout_fn_running = false;
- Timer is_typing_timer = new Timer();
- private bool is_typing_timeout_fn() {
- if(is_typing) {
- if(is_typing_timer.elapsed() > 15) {
- is_typing = false;
- conversation_view.on_typing_changed(is_typing);
- is_typing_timeout_fn_running = false;
- return false;
- } else {
- // wait another second
- return true;
- }
- }
- // abort timeout function when is_typing is already false
- is_typing_timeout_fn_running = false;
- return false;
- }
-
- public void on_typing_changed(bool is_typing) {
- is_typing_timer.start();
- if(this.is_typing == is_typing) {
- return;
- }
- this.is_typing = is_typing;
-
- if(is_typing && !is_typing_timeout_fn_running) {
- is_typing_timeout_fn_running = true;
- Timeout.add(1, is_typing_timeout_fn);
- }
-
- conversation_view.on_typing_changed(is_typing);
- }
-
- private void add_filetransfer(FileTransfer ft) {
- FileTransferChatEntry entry = new FileTransferChatEntry(ft);
- entry.filetransfer_accepted.connect((ft) => { filetransfer_accepted(ft); });
- entry.filetransfer_rejected.connect((ft) => { filetransfer_rejected(ft); });
- conversation_view.add_filetransfer(entry);
- }
-
- //history
-
- public void load_history(GLib.List messages) {
- messages.foreach((message) => {
- conversation_view.add_message(message);
- });
- }
-
- //drag-and-drop
-
- private void setup_drag_drop() {
- const Gtk.TargetEntry[] targets = {
- {"text/uri-list",0,0}
- };
- Gtk.drag_dest_set(this,Gtk.DestDefaults.ALL, targets, Gdk.DragAction.COPY);
- this.drag_data_received.connect(this.on_drag_data_received);
- }
-
-
- public void on_incoming_message(Message message) {
- if(message.from != contact)
- return;
- conversation_view.add_message(message);
- }
-
- public void on_incoming_filetransfer(FileTransfer ft) {
- add_filetransfer(ft);
- }
-
- public void textview_activate() {
- string s = message_textview.buffer.text;
- if(!contact.online || message_textview.placeholder_visible || s == "") {
- return;
- }
-
- GLib.MatchInfo info = null;
- if(Tools.action_regex.match(s, 0, out info) && info.fetch_named("action_name") == "me") {
- string action_string = info.fetch_named("action_string");
- if(action_string == null) {
- action_string = "";
- }
- ActionMessage a = new ActionMessage.outgoing(contact, action_string);
- conversation_view.add_message(a);
- new_outgoing_action(a);
- } else {
- Message m = new Message.outgoing(contact, s);
- conversation_view.add_message(m);
- new_outgoing_message(m);
- }
- message_textview.buffer.text = "";
- }
-
- //GUI events
- public void button_send_file_clicked(Gtk.Button source){
- Gtk.FileChooserDialog file_selection_dialog = new Gtk.FileChooserDialog(_("Select a file to send"),null,
- Gtk.FileChooserAction.OPEN,
- "_Cancel", Gtk.ResponseType.CANCEL,
- _("Select"), Gtk.ResponseType.ACCEPT);
- int response = file_selection_dialog.run();
- if(response != Gtk.ResponseType.ACCEPT){
- file_selection_dialog.destroy();
- return;
- }
- File file = file_selection_dialog.get_file();
- file_selection_dialog.destroy();
- prepare_send_file(file);
- }
-
- private void on_drag_data_received(Gtk.Widget sender, Gdk.DragContext drag_context, int x, int y, Gtk.SelectionData data, uint info, uint time) {
- string[] uris = data.get_uris();
-
- foreach (string uri in uris) {
- File file = File.new_for_uri(uri);
- prepare_send_file(file);
- }
- Gtk.drag_finish (drag_context, true, false, time);
- }
-
- private void prepare_send_file(File file) {
- uint64 file_size;
- try {
- file_size = file.query_info ("*", FileQueryInfoFlags.NONE).get_size ();
- } catch (Error e) {
- Logger.log(LogLevel.ERROR, "Error occured while getting file size: " + e.message);
- return;
- }
- FileTransfer ft = new FileTransfer(contact, FileTransferDirection.OUTGOING, file_size, file.get_basename(), file.get_path() );
- new_outgoing_file(ft);
- add_filetransfer(ft);
- }
-
- private void prepare_send_data(string name, uint8[] data) {
- FileTransfer ft = new FileTransfer.senddata(contact, name, data);
- new_outgoing_file(ft);
- add_filetransfer(ft);
- }
- }
-}
\ No newline at end of file
diff --git a/src/ui/EditableLabel.vala b/src/ui/EditableLabel.vala
deleted file mode 100644
index 9389b1e..0000000
--- a/src/ui/EditableLabel.vala
+++ /dev/null
@@ -1,153 +0,0 @@
-/*
- * EditableLabel.vala
- *
- * Copyright (C) 2013-2014 Venom authors and contributors
- *
- * This file is part of Venom.
- *
- * Venom is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * Venom is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with Venom. If not, see .
- */
-
-namespace Venom {
- public class EditableLabel : Gtk.EventBox {
- private Gtk.Box box_entry;
- private Gtk.Box box_label;
-
- public Gtk.Button button_cancel { get; set; }
- public Gtk.Button button_ok { get; set; }
- public Gtk.Entry entry { get; set; }
- public Gtk.Label label { get; set; }
-
- public signal void label_changed(string label_text);
- public signal void show_entry();
- public signal void show_label();
-
- public EditableLabel(string label = "") {
- this.label = new Gtk.Label(label);
- init_widgets();
- init_signals();
- }
-
- public EditableLabel.with_label(Gtk.Label label) {
- this.label = label;
- init_widgets();
- init_signals();
- }
-
- private void on_show_label() {
- box_label.visible = true;
- box_entry.visible = false;
- }
-
- private void on_show_entry() {
-//FIXME apparently not working on gtk 3.6.4
-//FIXME define GTK__ in cmake instead of using glib version
-//#if GLIB_2_34
-// entry.attributes = label.attributes;
-//#endif
- box_label.visible = false;
- box_entry.no_show_all = false;
- box_entry.show_all();
- box_entry.visible = true;
- box_entry.no_show_all = true;
- }
-
- private void init_widgets() {
- entry = new Gtk.Entry();
- button_ok = new Gtk.Button();
- button_cancel = new Gtk.Button();
-
- entry.has_frame = false;
- entry.width_chars = 10;
-
- button_ok.add(new Gtk.Image.from_pixbuf(ResourceFactory.instance.ok));
- button_cancel.add(new Gtk.Image.from_pixbuf(ResourceFactory.instance.cancel));
-
- Gtk.Box box = new Gtk.Box(Gtk.Orientation.VERTICAL, 0);
- box_label = new Gtk.Box(Gtk.Orientation.HORIZONTAL, 0);
- box_entry = new Gtk.Box(Gtk.Orientation.HORIZONTAL, 0);
- box_entry.spacing = 1;
-
- box_label.pack_start(label);
- box_entry.pack_start(entry);
- box_entry.pack_start(button_ok, false);
- box_entry.pack_start(button_cancel, false);
- box.pack_start(box_label);
- box.pack_start(box_entry);
-
- box_entry.no_show_all = true;
- box_entry.visible = false;
- this.add(box);
- }
-
- private void on_cancel() {
- show_label();
- }
-
- private void on_ok() {
- show_label();
- label_changed(entry.text);
- }
-
- private bool check_focus() {
- unowned Gtk.Widget w = get_toplevel();
- if(!w.is_toplevel() || !(w is Gtk.Window)) {
- //could not get window for some reason, abort
- Logger.log(LogLevel.ERROR, "Could not get reference to toplevel window");
- return false;
- }
- unowned Gtk.Widget focus_widget = (w as Gtk.Window).get_focus();
- if(focus_widget == null) {
- return false;
- }
- if(focus_widget != entry && focus_widget != button_ok && focus_widget != button_cancel) {
- // other widget focused
- on_cancel();
- }
- return false;
- }
-
- private bool on_focus_out(Gdk.EventFocus focus) {
- Idle.add(check_focus);
- return false;
- }
-
- private void init_signals() {
- show_entry.connect(on_show_entry);
- show_label.connect(on_show_label);
- button_press_event.connect((event) => {
- if(!box_entry.visible && event.button == Gdk.BUTTON_PRIMARY) {
- entry.text = label.label;
- show_entry();
- entry.grab_focus();
- return true;
- }
- return false;
- });
- button_cancel.clicked.connect(on_cancel);
- button_ok.clicked.connect(on_ok);
- entry.activate.connect(on_ok);
- entry.key_release_event.connect((event) => {
- if(event.keyval == Gdk.Key.Escape) {
- on_cancel();
- return true;
- }
- return false;
- });
- entry.focus_out_event.connect(on_focus_out);
- button_ok.focus_out_event.connect(on_focus_out);
- button_cancel.focus_out_event.connect(on_focus_out);
- }
- }
-}
diff --git a/src/ui/FileTransferChatEntry.vala b/src/ui/FileTransferChatEntry.vala
deleted file mode 100644
index b44a471..0000000
--- a/src/ui/FileTransferChatEntry.vala
+++ /dev/null
@@ -1,182 +0,0 @@
-/*
- * Copyright (C) 2013 Venom authors and contributors
- *
- * This file is part of Venom.
- *
- * Venom is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * Venom is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with Venom. If not, see .
- */
-
-namespace Venom {
- public class FileTransferChatEntry : Gtk.EventBox {
- public unowned FileTransfer ft;
-
- private Gtk.Label name_label;
- private Gtk.Label size_or_status_label;
- private Gtk.ProgressBar progress_bar;
- private Gtk.Button save_as_button;
- private Gtk.Button cancel_button;
-
- public signal void filetransfer_accepted(FileTransfer ft);
- public signal void filetransfer_rejected(FileTransfer ft);
- public signal void filetransfer_completed(FileTransferChatEntry entry, FileTransfer ft);
-
- public FileTransferChatEntry(FileTransfer ft){
- this.ft = ft;
- Gtk.Builder builder = new Gtk.Builder();
- try {
- builder.add_from_resource("/org/gtk/venom/chat_filetransfer.ui");
- } catch (GLib.Error e) {
- Logger.log(LogLevel.FATAL, "Loading message widget failed: " + e.message);
- }
- this.get_style_context().add_class("filetransfer_entry");
- //Gtk.Box box = builder.get_object("box1") as Gtk.Box;
- Gtk.Frame frame = builder.get_object("frame1") as Gtk.Frame;
- this.add(frame);
- frame.get_style_context().add_class("frame");
-
- name_label = builder.get_object("name_label") as Gtk.Label;
- size_or_status_label = builder.get_object("size_label") as Gtk.Label;
- progress_bar = builder.get_object("progress_bar") as Gtk.ProgressBar;
- progress_bar.can_focus = false;
- save_as_button = builder.get_object("save_as_button") as Gtk.Button;
- cancel_button = builder.get_object("cancel_button") as Gtk.Button;
- if( ft.direction == FileTransferDirection.OUTGOING ) {
- save_as_button.visible = false;
- }
-
- name_label.set_text( ft.name );
- size_or_status_label.set_text( UITools.format_filesize( ft.file_size ) );
-
- save_as_button.clicked.connect(accept_file);
- cancel_button.clicked.connect(reject_file);
-
- //filetransfer signals
- ft.progress_update.connect(update_progress);
- ft.status_changed.connect(status_changed);
-
- this.no_show_all = true;
- }
-
- private void update_progress(uint64 bytes_processed, uint64 file_size) {
- double progress = (double) bytes_processed / file_size;
- Idle.add( () => {progress_bar.set_fraction(progress);return false;} );
- }
-
- private void disable_buttons(){
- save_as_button.visible = false;
- cancel_button.visible = false;
- }
-
- private void status_changed(FileTransferStatus status,FileTransferDirection direction){
- switch (status) {
- case FileTransferStatus.DONE: {
- if(direction == FileTransferDirection.INCOMING) {
- size_or_status_label.set_text(_("File received"));
- } else if (direction == FileTransferDirection.OUTGOING) {
- size_or_status_label.set_text(_("File sent"));
- }
- progress_bar.visible = false;
- disable_buttons();
- filetransfer_completed(this, ft);
- } break;
- case FileTransferStatus.REJECTED: {
- size_or_status_label.set_text(_("File was rejected"));
- progress_bar.visible = false;
- disable_buttons();
- } break;
- case FileTransferStatus.IN_PROGRESS: {
- save_as_button.visible = false;
- size_or_status_label.set_text( UITools.format_filesize( ft.file_size ) );
- cancel_button.visible = true;
- } break;
- case FileTransferStatus.PAUSED: {
- size_or_status_label.set_text(_("Paused"));
- } break;
- case FileTransferStatus.SENDING_FAILED: {
- size_or_status_label.set_text(_("Sending failed"));
- size_or_status_label.get_style_context().add_class("error");
- progress_bar.visible = false;
- disable_buttons();
- } break;
- case FileTransferStatus.RECEIVING_FAILED: {
- size_or_status_label.set_text(_("Receiving failed"));
- size_or_status_label.get_style_context().add_class("error");
- progress_bar.visible = false;
- disable_buttons();
- } break;
- case FileTransferStatus.CANCELED: {
- size_or_status_label.set_text(_("Canceled"));
- progress_bar.visible = false;
- disable_buttons();
- } break;
-
- case FileTransferStatus.SENDING_BROKEN: {
- size_or_status_label.set_text(_("Disconnected"));
- } break;
-
- case FileTransferStatus.RECEIVING_BROKEN: {
- size_or_status_label.set_text(_("Disconnected"));
- } break;
-
- default:
- GLib.assert_not_reached();
- }
- }
-
- private void reject_file() {
- if(ft.status != FileTransferStatus.PENDING) {
- return;
- }
-
- if(ft.direction == FileTransferDirection.OUTGOING) {
- ft.status = FileTransferStatus.CANCELED;
- } else {
- ft.status = FileTransferStatus.REJECTED;
- }
- filetransfer_rejected(ft);
- }
-
- private void accept_file() {
- if(ft.status != FileTransferStatus.PENDING) {
- return;
- }
-
- Gtk.FileChooserDialog file_selection_dialog = new Gtk.FileChooserDialog(_("Save file"),null,
- Gtk.FileChooserAction.SAVE,
- "_Cancel", Gtk.ResponseType.CANCEL,
- _("Save"), Gtk.ResponseType.ACCEPT);
- file_selection_dialog.do_overwrite_confirmation = true;
- file_selection_dialog.set_current_name(ft.name);
- int res = file_selection_dialog.run();
- if(res == Gtk.ResponseType.ACCEPT) {
- string path = file_selection_dialog.get_filename();
- file_selection_dialog.destroy();
- Logger.log(LogLevel.INFO, "Saving to: " + path);
- File file = File.new_for_path(path);
- if(file.query_exists()){
- try {
- file.replace(null,false,FileCreateFlags.REPLACE_DESTINATION);
- } catch(Error e) {
- Logger.log(LogLevel.ERROR, "Error while trying to create file: " + e.message);
- }
- }
- filetransfer_accepted(ft);
- ft.status = FileTransferStatus.IN_PROGRESS;
- ft.path = path;
- return;
- }
- file_selection_dialog.destroy();
- }
- }
-}
diff --git a/src/ui/GroupConversationSidebar.vala b/src/ui/GroupConversationSidebar.vala
deleted file mode 100644
index 0367625..0000000
--- a/src/ui/GroupConversationSidebar.vala
+++ /dev/null
@@ -1,155 +0,0 @@
-/*
- * GroupConversationSidebar.vala
- *
- * Copyright (C) 2013-2014 Venom authors and contributors
- *
- * This file is part of Venom.
- *
- * Venom is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * Venom is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with Venom. If not, see .
- */
-namespace Venom {
- public interface IGroupConversationSidebar : Gtk.Widget {
- public abstract GroupChat groupchat { get; set; }
- public abstract void update_contact(int peernumber, Tox.ChatChange change);
- public abstract Gtk.TreeModel model { get; set; }
- }
-
- public class GroupConversationSidebar : Gtk.TreeView, IGroupConversationSidebar {
-
- public enum TreeModelColumn {
- ID,
- NAME,
- COLLATE_KEY
- }
-
- Gtk.ListStore listmodel;
- public GroupChat groupchat { get; set; }
- public GroupConversationSidebar( GroupChat groupchat ) {
- this.groupchat = groupchat;
- listmodel = new Gtk.ListStore (3, typeof(int), typeof(string), typeof(string));
- Gtk.TreeModelSort sort = new Gtk.TreeModelSort.with_model(listmodel);
- sort.set_sort_func(TreeModelColumn.NAME, sort_name);
- sort.set_sort_column_id(TreeModelColumn.NAME, Gtk.SortType.ASCENDING);
- set_model (sort);
-
- insert_column_with_attributes (-1, "Name", new Gtk.CellRendererText(),
- "markup", TreeModelColumn.NAME);
- init_contacts();
-
- query_tooltip.connect_after(modify_tooltip);
- has_tooltip = true;
- }
-
- private void init_contacts() {
- listmodel.clear();
- groupchat.peers.foreach ((key, val) => {
- GroupChatContact gcc = val as GroupChatContact;
- add_contact(gcc.group_contact_id, gcc.get_name_string());
- });
- }
-
- private bool modify_tooltip(int x, int y, bool keyboard_tooltip, Gtk.Tooltip tooltip) {
- Gtk.TreeModel model;
- Gtk.TreePath path;
- Gtk.TreeIter iter;
- if(!get_tooltip_context(ref x, ref y, keyboard_tooltip, out model, out path, out iter))
- return false;
- if(model == null)
- return false;
- GLib.Value v;
- model.get_value(iter, TreeModelColumn.ID, out v);
- GroupChatContact c = groupchat.peers.get(v.get_int());
- tooltip.set_markup(c.get_tooltip_string());
-
- set_tooltip_row(tooltip, path);
- return true;
- }
-
- private int sort_name(Gtk.TreeModel model, Gtk.TreeIter a, Gtk.TreeIter b) {
- int ret = 0;
- string string_a, string_b;
- model.get(a, TreeModelColumn.COLLATE_KEY, out string_a, -1);
- model.get(b, TreeModelColumn.COLLATE_KEY, out string_b, -1);
- if(string_a == null || string_b == null) {
- if(string_a == null && string_b == null) {
- return ret;
- }
- ret = (string_b == null) ? 1 : -1;
- } else {
- ret = string_a > string_b ? 1 : -1;
- }
- return ret;
- }
-
- private void set_contact(Gtk.TreeIter iter, int id, string name) {
- string collate_key = name.casefold().collate_key();
- listmodel.set(iter, TreeModelColumn.ID, id,
- TreeModelColumn.NAME, name,
- TreeModelColumn.COLLATE_KEY, collate_key);
- }
-
- private void add_contact(int peernumber, string? name) {
- Gtk.TreeIter? iter = find_contact(peernumber);
- if(iter == null) {
- listmodel.append (out iter);
- }
- set_contact(iter, peernumber, name);
- }
-
- private Gtk.TreeIter? find_contact(int peernumber) {
- Gtk.TreeIter iter;
- if( listmodel.get_iter_first(out iter) ) {
- do {
- GLib.Value val;
- listmodel.get_value(iter, TreeModelColumn.ID, out val);
- if(val.get_int() == peernumber) {
- return iter;
- }
- } while( listmodel.iter_next(ref iter) );
- }
-
- return null;
- }
-
- private void update_contact_name(int peernumber, string new_name) {
- Gtk.TreeIter? iter = find_contact(peernumber);
- if(iter != null) {
- set_contact(iter, peernumber, new_name);
- } else {
- Logger.log(LogLevel.ERROR, "Sidebar could not update peer #%i".printf(peernumber));
- }
- }
-
- private void delete_contact(int peernumber) {
- Gtk.TreeIter? iter = find_contact(peernumber);
- if(iter != null) {
- listmodel.remove(iter);
- } else {
- Logger.log(LogLevel.ERROR, "Sidebar could not remove peer #%i".printf(peernumber));
- }
- }
-
- public void update_contact(int peernumber, Tox.ChatChange change) {
- if(change == Tox.ChatChange.PEER_ADD) {
- add_contact(peernumber, groupchat.peers.get(peernumber).get_name_string());
- } else if(change == Tox.ChatChange.PEER_DEL) {
- delete_contact(peernumber);
- } else if(change == Tox.ChatChange.PEER_NAME) {
- update_contact_name(peernumber, groupchat.peers.get(peernumber).get_name_string());
- } else {
- GLib.assert_not_reached();
- }
- }
- }
-}
diff --git a/src/ui/GroupConversationWidget.vala b/src/ui/GroupConversationWidget.vala
deleted file mode 100644
index 238c968..0000000
--- a/src/ui/GroupConversationWidget.vala
+++ /dev/null
@@ -1,191 +0,0 @@
-/*
- * GroupConversationWidget.vala
- *
- * Copyright (C) 2013-2014 Venom authors and contributors
- *
- * This file is part of Venom.
- *
- * Venom is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * Venom is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with Venom. If not, see .
- */
-
-namespace Venom {
- public class GroupConversationWidget : Gtk.EventBox {
- private EditableLabel label_groupchat_name;
- private Gtk.Label label_groupchat_statusmessage;
- private Gtk.Image image_groupchat_image;
-
- private MessageTextView message_textview;
-
- private IConversationView conversation_view;
- private IGroupConversationSidebar group_conversation_sidebar;
-
- private unowned GroupChat groupchat {get; private set;}
-
- public signal void new_outgoing_message(GroupMessage message);
- public signal void new_outgoing_action(GroupActionMessage action);
- public signal void groupchat_changed(GroupChat g);
-
- public GroupConversationWidget( GroupChat groupchat ) {
- this.groupchat = groupchat;
- init_widgets();
- update_groupchat_info();
- }
-
- public void update_groupchat_info() {
- // update groupchat name
- label_groupchat_name.label.label = _("%s").printf(groupchat.get_name_string_with_hyperlinks());
-
- // update groupchat status message
- label_groupchat_statusmessage.label = groupchat.get_status_string_with_hyperlinks();
-
- // update groupchat image
- image_groupchat_image.set_from_pixbuf(groupchat.image != null ? groupchat.image : ResourceFactory.instance.default_groupchat);
- }
-
- public void update_contact(int peernumber, Tox.ChatChange change) {
- if(change == Tox.ChatChange.PEER_ADD || change == Tox.ChatChange.PEER_DEL) {
- update_groupchat_info();
- }
- // update sidebar
- group_conversation_sidebar.update_contact(peernumber, change);
- }
-
- private void init_widgets() {
- Gtk.Builder builder = new Gtk.Builder();
- try {
- builder.add_from_resource("/org/gtk/venom/conversation_window.ui");
- } catch (GLib.Error e) {
- Logger.log(LogLevel.FATAL, "Loading conversation window failed: " + e.message);
- }
- Gtk.Box box = builder.get_object("box") as Gtk.Box;
- this.add(box);
- this.get_style_context().add_class("conversation_widget");
- label_groupchat_statusmessage = builder.get_object("label_contact_statusmessage") as Gtk.Label;
- image_groupchat_image = builder.get_object("image_contact_image") as Gtk.Image;
-
- Gtk.Image image_send = builder.get_object("image_send") as Gtk.Image;
- Gtk.Image image_call = builder.get_object("image_call") as Gtk.Image;
- Gtk.Image image_call_video = builder.get_object("image_call_video") as Gtk.Image;
- Gtk.Image image_send_file = builder.get_object("image_send_file") as Gtk.Image;
- Gtk.Image image_insert_smiley = builder.get_object("image_insert_smiley") as Gtk.Image;
-
- Gtk.Label label_groupchat_name_ = builder.get_object("label_contact_name") as Gtk.Label;
- Gtk.Box box_user_info = builder.get_object("box_user_info") as Gtk.Box;
- box_user_info.remove(label_groupchat_name_);
- label_groupchat_name = new EditableLabel.with_label(label_groupchat_name_);
- box_user_info.pack_start(label_groupchat_name, false);
- label_groupchat_name.button_cancel.get_style_context().add_class("callbutton");
- label_groupchat_name.button_ok.get_style_context().add_class("callbutton");
- label_groupchat_name.show_all();
- label_groupchat_name.show_entry.connect_after(() => {
- label_groupchat_name.entry.text = groupchat.local_name;
- });
- label_groupchat_name.label_changed.connect((new_name) => {
- groupchat.local_name = new_name;
- groupchat_changed(groupchat);
- });
-
- //TODO
- //Gtk.Button button_call = builder.get_object("button_call") as Gtk.Button;
- //Gtk.Button button_call_video = builder.get_object("button_call_video") as Gtk.Button;
- Gtk.Button button_send = builder.get_object("button_send") as Gtk.Button;
- //Gtk.Button button_send_file = builder.get_object("button_send_file") as Gtk.Button;
-
- //button_send_file.clicked.connect(button_send_file_clicked);
-
- Gtk.Paned paned_sidebar = builder.get_object("paned_sidebar") as Gtk.Paned;
- Gtk.ScrolledWindow sidebar_scrolled_window = new Gtk.ScrolledWindow(null, null);
- group_conversation_sidebar = new GroupConversationSidebar(groupchat);
- sidebar_scrolled_window.add(group_conversation_sidebar);
- sidebar_scrolled_window.show_all();
- paned_sidebar.pack2(sidebar_scrolled_window, false, true);
-
- Gtk.ScrolledWindow scrolled_window_message = builder.get_object("scrolled_window_message") as Gtk.ScrolledWindow;
- message_textview = new MessageTextView();
- message_textview.border_width = 6;
- message_textview.wrap_mode = Gtk.WrapMode.WORD_CHAR;
- message_textview.textview_activate.connect(textview_activate);
- message_textview.completion_column = GroupConversationSidebar.TreeModelColumn.NAME;
- message_textview.completion_model = group_conversation_sidebar.model;
- scrolled_window_message.add(message_textview);
-
- button_send.clicked.connect(textview_activate);
-
- image_send.set_from_pixbuf(ResourceFactory.instance.send);
- image_call.set_from_pixbuf(ResourceFactory.instance.call);
- image_call_video.set_from_pixbuf(ResourceFactory.instance.call_video);
- image_send_file.set_from_pixbuf(ResourceFactory.instance.send_file);
- image_insert_smiley.set_from_pixbuf(ResourceFactory.instance.smiley);
-
- Gtk.ScrolledWindow scrolled_window = builder.get_object("scrolled_window") as Gtk.ScrolledWindow;
-
- if( ResourceFactory.instance.textview_mode ) {
- conversation_view = new ConversationTextView();
- scrolled_window.add(conversation_view);
- } else {
- conversation_view = new ConversationView();
- scrolled_window.add_with_viewport(conversation_view);
- }
- conversation_view.get_style_context().add_class("chat_list");
- conversation_view.short_names = false;
-
- Gtk.Overlay overlay = builder.get_object("overlay") as Gtk.Overlay;
- Gtk.Entry entry_search = new SearchEntry();
- entry_search.halign = Gtk.Align.END;
- entry_search.valign = Gtk.Align.START;
- entry_search.no_show_all = true;
- conversation_view.register_search_entry(entry_search);
- overlay.add_overlay(entry_search);
-
- Gtk.Adjustment vadjustment = scrolled_window.get_vadjustment();
- bool scroll_to_bottom = true;
- conversation_view.size_allocate.connect( () => {
- if(scroll_to_bottom) {
- vadjustment.value = vadjustment.upper - vadjustment.page_size;
- }
- });
- vadjustment.value_changed.connect( () => {
- scroll_to_bottom = (vadjustment.value == vadjustment.upper - vadjustment.page_size);
- });
-
- delete_event.connect(hide_on_delete);
- }
-
- public void on_incoming_message(GroupMessage message) {
- if(message.from != groupchat)
- return;
-
- conversation_view.add_message(message);
- }
-
- public void textview_activate() {
- string s = message_textview.buffer.text;
- if(s == "" || message_textview.placeholder_visible)
- return;
- GLib.MatchInfo info = null;
- if(Tools.action_regex.match(s, 0, out info) && info.fetch_named("action_name") == "me") {
- string action_string = info.fetch_named("action_string");
- if(action_string == null) {
- action_string = "";
- }
- GroupActionMessage a = new GroupActionMessage.outgoing(groupchat, action_string);
- new_outgoing_action(a);
- } else {
- GroupMessage m = new GroupMessage.outgoing(groupchat, s);
- new_outgoing_message(m);
- }
- message_textview.buffer.text = "";
- }
- }
-}
diff --git a/src/ui/MessageTextView.vala b/src/ui/MessageTextView.vala
deleted file mode 100644
index 4aea5af..0000000
--- a/src/ui/MessageTextView.vala
+++ /dev/null
@@ -1,169 +0,0 @@
-/*
- * MessageTextView.vala
- *
- * Copyright (C) 2013-2014 Venom authors and contributors
- *
- * This file is part of Venom.
- *
- * Venom is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * Venom is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with Venom. If not, see .
- */
-
-namespace Venom {
- public class MessageTextView : Gtk.TextView {
- public signal void textview_activate();
- public signal void typing_status(bool typing);
-
- public string placeholder_text { get; set; default = _("Type your message here..."); }
- public Gtk.TextTag placeholder_tag { get; set; }
- public bool placeholder_visible { get; protected set; default = true; }
-
- private Gtk.TreeModel _completion_model;
- public Gtk.TreeModel completion_model {
- get {
- return _completion_model;
- } set {
- _completion_model = value;
- completion_filtered = new Gtk.TreeModelFilter(_completion_model, null);
- completion_filtered.set_visible_func(visible_function);
- }
- }
- public int completion_column { get; set; }
-
- private bool is_typing = false;
- private Gtk.TreeModelFilter completion_filtered;
- private string filter_string;
-
- public MessageTextView() {
- /** Placeholder **/
- placeholder_tag = buffer.create_tag(null, "foreground", "grey");
- append_tagged_text(placeholder_text, placeholder_tag);
-
- /** Events **/
- key_press_event.connect(on_key_press);
-
- focus_in_event.connect(() => {
- if(placeholder_visible) {
- placeholder_visible = false;
- buffer.text = "";
- }
- return false;
- });
-
- focus_out_event.connect(() => {
- if(buffer.text == "") {
- placeholder_visible = true;
- append_tagged_text(placeholder_text, placeholder_tag);
- } else {
- placeholder_visible = false;
- }
- return false;
- });
-
- buffer.changed.connect(on_buffer_changed);
- }
-
- // changes typing status to false after >= 5 seconds of inactivity
- bool is_typing_timeout_fn_running = false;
- Timer is_typing_timer = new Timer();
- private bool is_typing_timeout_fn() {
- if(is_typing) {
- if(is_typing_timer.elapsed() > 5) {
- is_typing = false;
- typing_status(is_typing);
- is_typing_timeout_fn_running = false;
- return false;
- } else {
- // wait another second
- return true;
- }
- }
- // abort timeout function when is_typing is already false
- is_typing_timeout_fn_running = false;
- return false;
- }
- Timer continuous_typing_timeout = new Timer();
- private void on_buffer_changed() {
- is_typing_timer.start();
- if(placeholder_visible || buffer.text._chug() == "") {
- if(is_typing) {
- is_typing = false;
- typing_status(is_typing);
- }
- } else if(!is_typing || continuous_typing_timeout.elapsed() > 2) {
- continuous_typing_timeout.start();
- is_typing = true;
- typing_status(is_typing);
- if(!is_typing_timeout_fn_running) {
- is_typing_timeout_fn_running = true;
- Timeout.add(1, is_typing_timeout_fn);
- }
- }
- }
-
- private bool visible_function(Gtk.TreeModel model, Gtk.TreeIter iter) {
- string str;
- model.get(iter, completion_column, out str, -1);
- return (str != null && filter_string != null &&
- str.casefold().has_prefix(filter_string.casefold()));
- }
-
- private bool on_key_press(Gdk.EventKey event) {
- // only catch return if shift or control keys are not pressed
- if(event.keyval == Gdk.Key.Return && (event.state & (Gdk.ModifierType.SHIFT_MASK | Gdk.ModifierType.CONTROL_MASK)) == 0) {
- textview_activate();
- return true;
- } else if(event.keyval == Gdk.Key.Tab) {
- if(completion_model == null) {
- // behave as the default textview
- return false;
- }
-
- Gtk.TextMark ohaimark = buffer.get_insert();
- Gtk.TextIter iter_end;
- buffer.get_iter_at_mark(out iter_end, ohaimark);
-
- if(!iter_end.ends_word()) {
- return true;
- }
-
- Gtk.TextIter iter_start = iter_end;
- iter_start.backward_word_start();
-
- filter_string = iter_start.get_text(iter_end);
- completion_filtered.refilter();
-
- Gtk.TreeIter filter_iter;
- if( completion_filtered.get_iter_first(out filter_iter) ) {
- string completed_string;
- completion_filtered.get(filter_iter, completion_column, out completed_string, -1);
- buffer.delete(ref iter_start, ref iter_end);
- if(iter_start.starts_line()) {
- completed_string += ": ";
- } else {
- completed_string += " ";
- }
- buffer.insert(ref iter_start, completed_string, completed_string.length);
- }
- return true;
- }
- return false;
- }
-
- private void append_tagged_text(string text, Gtk.TextTag tag) {
- Gtk.TextIter text_end;
- buffer.get_end_iter(out text_end);
- buffer.insert_with_tags(text_end, text, text.length, tag);
- }
- }
-}
diff --git a/src/ui/PinDialog.vala b/src/ui/PinDialog.vala
deleted file mode 100644
index 58c2292..0000000
--- a/src/ui/PinDialog.vala
+++ /dev/null
@@ -1,55 +0,0 @@
-/*
- * GetPinDialog.vala
- *
- * Copyright (C) 2013-2014 Venom authors and contributors
- *
- * This file is part of Venom.
- *
- * Venom is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * Venom is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with Venom. If not, see .
- */
-
-namespace Venom {
- public class PinDialog : Gtk.Dialog {
- private Gtk.Entry pin_entry;
- public string pin {
- get { return pin_entry.text; }
- set { pin_entry.text = value; }
- }
- public PinDialog( string username ) {
-
- Gtk.Box content_box = new Gtk.Box (Gtk.Orientation.VERTICAL, 0);
- content_box.spacing = 6;
- content_box.margin_left = 5;
- content_box.margin_right = 5;
- content_box.margin_top = 5;
-
- Gtk.Label label_pin = new Gtk.Label(_("Please insert PIN for \n%s").printf(Markup.escape_text( username )));
- label_pin.use_markup = true;
- content_box.pack_start(label_pin, false, false, 0);
-
- pin_entry = new Gtk.Entry();
- pin_entry.activates_default = true;
- pin_entry.xalign = 0.5f;
- content_box.pack_start(pin_entry, false, false, 0);
-
- get_content_area().add(content_box);
-
- add_buttons("_Cancel", Gtk.ResponseType.CANCEL, "_Ok", Gtk.ResponseType.OK, null);
- title = _("Please insert PIN...");
- pin = "000000";
-
- set_default_response(Gtk.ResponseType.OK);
- }
- }
-}
diff --git a/src/ui/SettingsWindow.vala b/src/ui/SettingsWindow.vala
deleted file mode 100644
index 043bc20..0000000
--- a/src/ui/SettingsWindow.vala
+++ /dev/null
@@ -1,72 +0,0 @@
-/*
- * SettingsWindow.vala
- *
- * Copyright (C) 2013-2014 Venom authors and contributors
- *
- * This file is part of Venom.
- *
- * Venom is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * Venom is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with Venom. If not, see .
- */
-
-namespace Venom {
- public class SettingsWindow : GLib.Object {
- private Gtk.Dialog dialog;
- public signal void destroy();
-
- public SettingsWindow( Gtk.Window parent ) {
- Gtk.Builder builder = new Gtk.Builder();
- try {
- builder.add_from_resource("/org/gtk/venom/settings_window.ui");
- } catch (GLib.Error e) {
- Logger.log(LogLevel.FATAL, "Loading conversation window failed: " + e.message);
- }
- dialog = builder.get_object("dialog") as Gtk.Dialog;
- dialog.set_transient_for(parent);
-
- Settings settings = Settings.instance;
-
- settings.bind_property(Settings.MESSAGE_LOGGING_KEY, builder.get_object("keep_history_checkbutton"), "active", BindingFlags.SYNC_CREATE | BindingFlags.BIDIRECTIONAL);
- settings.bind_property(Settings.MESSAGE_LOGGING_KEY, builder.get_object("history_box"), "sensitive", BindingFlags.SYNC_CREATE);
- settings.bind_property(Settings.LOG_INDEFINITELY_KEY, builder.get_object("history_keep_radio"), "active", BindingFlags.SYNC_CREATE | BindingFlags.BIDIRECTIONAL);
- settings.bind_property(Settings.DAYS_TO_LOG_KEY, builder.get_object("history_delete_spinbutton"), "value", BindingFlags.SYNC_CREATE | BindingFlags.BIDIRECTIONAL);
- settings.bind_property(Settings.SEND_TYPING_STATUS_KEY, builder.get_object("send_typing_checkbutton"), "active", BindingFlags.SYNC_CREATE | BindingFlags.BIDIRECTIONAL);
- settings.bind_property(Settings.SHOW_TYPING_STATUS_KEY, builder.get_object("show_typing_checkbutton"), "active", BindingFlags.SYNC_CREATE | BindingFlags.BIDIRECTIONAL);
- settings.bind_property(Settings.URGENCY_NOTIFICATION_KEY, builder.get_object("urgency_notification_checkbutton"), "active", BindingFlags.SYNC_CREATE | BindingFlags.BIDIRECTIONAL);
- settings.bind_property(Settings.TRAY_KEY, builder.get_object("enable_tray_checkbutton"), "active", BindingFlags.SYNC_CREATE | BindingFlags.BIDIRECTIONAL);
-#if ENABLE_LIBNOTIFY
- settings.bind_property(Settings.NOTIFY_KEY, builder.get_object("notify_checkbutton"), "active", BindingFlags.SYNC_CREATE | BindingFlags.BIDIRECTIONAL);
-#else
- (builder.get_object("notify_checkbutton") as Gtk.Widget).sensitive = false;
-#endif
- settings.bind_property(Settings.DEFAULT_HOST_KEY, builder.get_object("default_host_entry"), "text", BindingFlags.SYNC_CREATE | BindingFlags.BIDIRECTIONAL);
- settings.bind_property(Settings.DEC_BINARY_PREFIX_KEY, builder.get_object("filesize_prefix_combobox"), "active", BindingFlags.SYNC_CREATE | BindingFlags.BIDIRECTIONAL,
- (binding, srcval, ref targetval) => {targetval.set_int((bool)srcval ? 0 : 1); return true;},
- (binding, srcval, ref targetval) => {targetval.set_boolean((int)srcval == 0); return true;}
- );
- }
-
- public void show_all() {
- dialog.show_all();
- dialog.response.connect( () => {
- Settings.instance.save_settings(ResourceFactory.instance.config_filename);
- dialog.destroy();
- destroy();
- });
- }
-
- public void present() {
- dialog.present();
- }
- }
-}
diff --git a/src/ui/UITools.vala b/src/ui/UITools.vala
deleted file mode 100644
index ee8b084..0000000
--- a/src/ui/UITools.vala
+++ /dev/null
@@ -1,169 +0,0 @@
-/*
- * UITools.vala
- *
- * Copyright (C) 2013-2014 Venom authors and contributors
- *
- * This file is part of Venom.
- *
- * Venom is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * Venom is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with Venom. If not, see .
- */
-
-namespace Venom {
- public class UITools : GLib.Object {
- public static void show_error_dialog(string message, string? secondary_text = null, Gtk.Window? parent = null) {
- Gtk.MessageDialog dialog = new Gtk.MessageDialog(
- parent,
- Gtk.DialogFlags.MODAL,
- Gtk.MessageType.ERROR,
- Gtk.ButtonsType.CLOSE,
- message,
- null
- );
- if(secondary_text != null)
- dialog.secondary_text = secondary_text;
- dialog.run();
- dialog.destroy();
- }
- public static string format_filesize(uint64 size) {
- if(Settings.instance.dec_binary_prefix) {
- uint64 kibibyte = 1024;
- uint64 mebibyte = kibibyte * 1024;
- uint64 gibibyte = mebibyte * 1024;
- uint64 tebibyte = gibibyte * 1024;
- uint64 pebibyte = tebibyte * 1024;
-
- if(size < kibibyte) return "%llu bytes".printf(size);
- if(size < mebibyte) return "%.2lf KiB".printf( (double) size / kibibyte );
- if(size < gibibyte) return "%.2lf MiB".printf( (double) size / mebibyte );
- if(size < tebibyte) return "%.2lf GiB".printf( (double) size / gibibyte );
- if(size < pebibyte) return "%.2lf TiB".printf( (double) size / tebibyte );
- return "really big file";
- } else {
- uint64 kilobyte = 1000;
- uint64 megabyte = kilobyte * 1000;
- uint64 gigabyte = megabyte * 1000;
- uint64 terabyte = gigabyte * 1000;
- uint64 petabyte = terabyte * 1000;
-
- if(size < kilobyte) return "%llu bytes".printf(size);
- if(size < megabyte) return "%.2lf kB".printf( (double) size / kilobyte );
- if(size < gigabyte) return "%.2lf MB".printf( (double) size / megabyte );
- if(size < terabyte) return "%.2lf GB".printf( (double) size / gigabyte );
- if(size < petabyte) return "%.2lf TB".printf( (double) size / terabyte );
- return "really big file";
- }
- }
-
- public static Gtk.Menu show_contact_context_menu( ContactListWindow w, Contact c ) {
- Gtk.Menu menu = new Gtk.Menu();
-/*
- Gtk.MenuItem item = new Gtk.MenuItem.with_mnemonic("_Show");
- item.activate.connect(() => { print("name: %s\n", c.get_name_string()); });
- menu.append(item);*/
-
- Gtk.MenuItem item = new Gtk.MenuItem.with_mnemonic(_("_Unfriend"));
- item.activate.connect(() => { w.remove_contact(c); });
- menu.append(item);
-/*
- item = new Gtk.MenuItem.with_mnemonic("_Block");
- item.activate.connect(() => { w.block_contact(c); });
- menu.append(item);*/
-
- GLib.HashTable groupchats = w.get_groupchats();
- if(groupchats.size() > 0) {
- Gtk.MenuItem groupchat_item = new Gtk.MenuItem.with_mnemonic(_("_Invite to ..."));
- Gtk.Menu groupchat_submenu = new Gtk.Menu();
-
- item = new Gtk.MenuItem.with_mnemonic(_("_New groupchat"));
- item.activate.connect(() => { w.invite_to_groupchat(c); });
- groupchat_submenu.append(item);
-
- groupchats.foreach((key, val) => {
- item = new Gtk.MenuItem.with_label(val.get_name_string());
- item.activate.connect(() => { w.invite_to_groupchat(c, key); });
- groupchat_submenu.append(item);
- });
- groupchat_item.submenu = groupchat_submenu;
- menu.append(groupchat_item);
- } else {
- item = new Gtk.MenuItem.with_mnemonic(_("_Invite to new groupchat"));
- item.activate.connect(() => { w.invite_to_groupchat(c); });
- menu.append(item);
- }
- return menu;
- }
-
- public static Gtk.Menu show_groupchat_context_menu( ContactListWindow w, GroupChat g ) {
- Gtk.Menu menu = new Gtk.Menu();
-
- Gtk.MenuItem item = new Gtk.MenuItem.with_mnemonic(_("_Leave groupchat"));
- item.activate.connect(() => { w.remove_groupchat(g ); });
- menu.append(item);
-
- return menu;
- }
-
- public static void export_datafile(Gtk.Window parent, ToxSession s) {
- Gtk.FileChooserDialog dialog = new Gtk.FileChooserDialog(
- _("Export tox data file"),
- parent,
- Gtk.FileChooserAction.SAVE,
- "_Cancel",
- Gtk.ResponseType.CANCEL,
- "_Save",
- Gtk.ResponseType.ACCEPT
- );
- dialog.set_filename(ResourceFactory.instance.data_filename);
- dialog.transient_for = parent;
- int ret = dialog.run();
- string filename = dialog.get_filename();
- dialog.destroy();
-
- if(ret != Gtk.ResponseType.ACCEPT) {
- return;
- }
- Logger.log(LogLevel.INFO, "Exporting data file to " + filename);
- try {
- s.save_to_file(filename);
- } catch (GLib.Error e) {
- Logger.log(LogLevel.ERROR, "Could not export data file: " + e.message);
- show_error_dialog(_("Exporting data file failed"), _("Could not export data file: ") + e.message, parent);
- }
- }
-
- public static void import_datafile(Gtk.Window parent, ToxSession s) {
- //TODO
- show_error_dialog(_("Importing data files is currently not supported"), "", parent);
- }
-
-#if ENABLE_QR_ENCODE
- public static Gdk.Pixbuf? qr_encode(string content) {
- QR.Code code = QR.Code.encode_string(content, 0, QR.ECLevel.M, QR.Mode.EIGHT_BIT, false);
- if(code == null) {
- return null;
- }
- Gdk.Pixbuf pb = new Gdk.Pixbuf(Gdk.Colorspace.RGB, false, 8, code.width, code.width);
- unowned uint8[] buf = pb.get_pixels();
- for(int y = 0; y < code.width; y++) {
- for(int x = 0; x < code.width; x++) {
- buf[y * pb.rowstride + x * pb.n_channels + 0] = code.get(x, y) ? 0 : 255;
- buf[y * pb.rowstride + x * pb.n_channels + 1] = code.get(x, y) ? 0 : 255;
- buf[y * pb.rowstride + x * pb.n_channels + 2] = code.get(x, y) ? 0 : 255;
- }
- }
- return pb.scale_simple(code.width * 4, code.width * 4, Gdk.InterpType.NEAREST);
- }
-#endif
- }
-}
diff --git a/src/ui/UserInfoWindow.vala b/src/ui/UserInfoWindow.vala
deleted file mode 100644
index 6416273..0000000
--- a/src/ui/UserInfoWindow.vala
+++ /dev/null
@@ -1,103 +0,0 @@
-/*
- * UserInfoWindow.vala
- *
- * Copyright (C) 2013-2014 Venom authors and contributors
- *
- * This file is part of Venom.
- *
- * Venom is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * Venom is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with Venom. If not, see .
- */
-
-namespace Venom {
- public class UserInfoWindow : Gtk.Dialog {
- protected Gtk.Widget button_apply;
- public string user_name {
- get { return entry_username.get_text(); }
- set { entry_username.set_text(value); }
- }
- public string user_status {
- get { return entry_statusmessage.get_text(); }
- set { entry_statusmessage.set_text(value); }
- }
- public Gdk.Pixbuf user_image {
- get { return image_userimage.get_pixbuf(); }
- set { image_userimage.set_from_pixbuf(value); }
- }
- public string user_id {
- set { label_id.set_text(value); }
- get { return label_id.get_text(); }
- }
- public int max_name_length {
- get { return entry_username.max_length; }
- set { entry_username.max_length = value; }
- }
- public int max_status_length {
- get { return entry_statusmessage.max_length; }
- set { entry_statusmessage.max_length = value; }
- }
-
- private Gtk.Entry entry_username;
- private Gtk.Entry entry_statusmessage;
- private Gtk.Image image_userimage;
- private Gtk.Label label_id;
- private Gtk.Image image_qr_code;
-
- public UserInfoWindow() {
- init_widgets();
- }
-
- private void init_widgets() {
- Gtk.Builder builder = new Gtk.Builder();
- try {
- builder.add_from_resource("/org/gtk/venom/user_info_window.ui");
- } catch (GLib.Error e) {
- Logger.log(LogLevel.FATAL, "Loading user info window failed: " + e.message);
- }
- Gtk.Box box = builder.get_object("box") as Gtk.Box;
- this.get_content_area().add(box);
-
- entry_username = builder.get_object("entry_username") as Gtk.Entry;
- entry_statusmessage = builder.get_object("entry_statusmessage") as Gtk.Entry;
- image_userimage = builder.get_object("image_userimage") as Gtk.Image;
- label_id = builder.get_object("label_id") as Gtk.Label;
- image_qr_code = builder.get_object("image_qr_code") as Gtk.Image;
- Gtk.Button button_copy_id = builder.get_object("button_copy_id") as Gtk.Button;
-
- entry_username.changed.connect(on_entry_changed);
- entry_statusmessage.changed.connect(on_entry_changed);
- button_copy_id.clicked.connect(() => {application.activate_action("copy-id", null);});
- notify["user-id"].connect(() => {on_id_changed();});
-
- this.add_button("_Cancel", Gtk.ResponseType.CANCEL);
- button_apply = this.add_button("_Apply", Gtk.ResponseType.APPLY);
-
- this.set_default_response(Gtk.ResponseType.APPLY);
- this.title = _("Edit user information");
- // set dialog to minimal size
- set_default_size(0, 0);
- }
-
- public void on_entry_changed() {
- button_apply.sensitive = (user_name != "" && user_status != "");
- }
-
- public void on_id_changed() {
-#if ENABLE_QR_ENCODE
- image_qr_code.pixbuf = UITools.qr_encode("tox:" + user_id);
- image_qr_code.show();
-#endif
- }
-
- }
-}
diff --git a/src/ui/add_contact_dialog.ui b/src/ui/add_contact_dialog.ui
deleted file mode 100644
index 2bc5a9c..0000000
--- a/src/ui/add_contact_dialog.ui
+++ /dev/null
@@ -1,135 +0,0 @@
-
-
-
-
-
-
-
diff --git a/src/ui/add_contact_widget.ui b/src/ui/add_contact_widget.ui
new file mode 100644
index 0000000..6e48bd7
--- /dev/null
+++ b/src/ui/add_contact_widget.ui
@@ -0,0 +1,409 @@
+
+
+
+
+
+
+
+
+ True
+ False
+ center
+ center
+ 6
+ vertical
+ 6
+
+
+ True
+ False
+ contact-new-symbolic
+ 6
+
+
+ False
+ True
+ 0
+
+
+
+
+ True
+ False
+ No new friend requests
+
+
+ False
+ True
+ 1
+
+
+
+
+
+ Please let me add you to my contact list. 😁
+
+
+ True
+ False
+ 6
+ 12
+
+
+ True
+ False
+ end
+ start
+ contact-new-symbolic
+ 6
+
+
+ True
+ True
+ 0
+
+
+
+
+ True
+ False
+ vertical
+ 6
+
+
+ True
+ False
+ crossfade
+
+
+ True
+ False
+ vertical
+ 6
+
+
+ True
+ False
+ Send a friend request
+ 0
+
+
+
+
+
+ False
+ True
+ 0
+
+
+
+
+ 450
+ True
+ False
+ none
+ False
+
+
+ True
+ True
+
+
+ True
+ False
+ 6
+ vertical
+ 6
+
+
+ True
+ False
+ _ID:
+ True
+ 0
+
+
+
+
+
+ False
+ True
+ 0
+
+
+
+
+ True
+ True
+ Enter a Tox ID or URI here
+ True
+ True
+ edit-paste-symbolic
+ paste from clipboard
+
+
+ False
+ True
+ 1
+
+
+
+
+ True
+ False
+
+
+ True
+ False
+ Error id
+ 0
+
+
+
+
+
+
+
+ False
+ True
+ 2
+
+
+
+
+ True
+ False
+ <small>Enter your friends Tox ID</small>
+ True
+ 0
+
+
+
+ False
+ True
+ 3
+
+
+
+
+
+
+
+
+ True
+ False
+
+
+ True
+ False
+ 6
+ vertical
+ 6
+
+
+ True
+ False
+ _Message:
+ True
+ 0
+
+
+
+
+
+ False
+ True
+ 0
+
+
+
+
+ 100
+ True
+ False
+
+
+ True
+ False
+
+
+ True
+ True
+ Send a custom message to be displayed to the friend you are adding
+ 6
+ word
+ textbuffer1
+
+
+
+
+
+
+
+ False
+ True
+ 1
+
+
+
+
+ True
+ False
+ <small>Send your friend a short message</small>
+ True
+ True
+ 0
+
+
+
+ False
+ True
+ 2
+
+
+
+
+
+
+
+
+
+ False
+ True
+ 1
+
+
+
+
+ Send
+ True
+ True
+ True
+
+
+
+ False
+ True
+ 2
+
+
+
+
+ page0
+ Add a friend
+
+
+
+
+ True
+ False
+ vertical
+ 6
+
+
+ True
+ False
+ Friend requests
+ 0
+
+
+
+
+
+ False
+ True
+ 0
+
+
+
+
+ 450
+ 350
+ True
+ False
+ none
+ False
+
+
+
+ True
+ True
+ 1
+
+
+
+
+ page1
+ Friend requests
+ 1
+
+
+
+
+ False
+ True
+ 1
+
+
+
+
+ False
+ True
+ 1
+
+
+
+
+ True
+ False
+ vertical
+
+
+ True
+ True
+ 2
+
+
+
+
+ True
+ False
+ center
+ stack
+
+
diff --git a/src/ui/app_menu.ui b/src/ui/app_menu.ui
new file mode 100644
index 0000000..c2e366e
--- /dev/null
+++ b/src/ui/app_menu.ui
@@ -0,0 +1,43 @@
+
+
+
+
+
+
+
+
+
diff --git a/src/ui/application_window.ui b/src/ui/application_window.ui
new file mode 100644
index 0000000..1d7d622
--- /dev/null
+++ b/src/ui/application_window.ui
@@ -0,0 +1,170 @@
+
+
+
+
+
+
+
+
+ False
+
+
+ True
+ False
+
+
+
+ True
+ True
+ end
+ 0
+
+
+
+
+
+ False
+ True
+ 1
+
+
+
+
+
+
+ True
+ True
+
+
+ True
+ False
+ vertical
+
+
+ False
+ False
+
+
+
+
+ True
+ True
+
+
+ True
+ False
+
+
+ True
+ False
+ crossfade
+ 200
+ True
+
+
+
+
+
+
+ True
+ False
+
+
+
+
+
+
+ venom-symbolic
+ venom
+
+
diff --git a/src/ui/chat_filetransfer.ui b/src/ui/chat_filetransfer.ui
deleted file mode 100644
index c5257fa..0000000
--- a/src/ui/chat_filetransfer.ui
+++ /dev/null
@@ -1,134 +0,0 @@
-
-
-
-
-
- 400
- True
- False
- 0
- none
-
-
- True
- False
- 12
- 12
- 12
- 12
-
-
- True
- False
- vertical
- 6
-
-
- True
- False
- 6
-
-
- True
- False
- #filename
- middle
- 30
-
-
-
- False
- True
- 0
-
-
-
-
- True
- False
- #size
-
-
-
- False
- True
- 1
-
-
-
-
- False
- True
- 0
-
-
-
-
- 100
- 10
- True
- False
- False
-
-
- False
- False
- 1
-
-
-
-
- True
- False
- 6
- end
-
-
- gtk-cancel
- 0
- True
- False
- False
- True
-
-
- False
- False
- 0
-
-
-
-
- gtk-save-as
- 0
- True
- False
- False
- True
-
-
- False
- False
- 1
-
-
-
-
- False
- True
- 2
-
-
-
-
-
-
-
-
-
-
-
diff --git a/src/ui/conference_info_widget.ui b/src/ui/conference_info_widget.ui
new file mode 100644
index 0000000..cbfaef1
--- /dev/null
+++ b/src/ui/conference_info_widget.ui
@@ -0,0 +1,340 @@
+
+
+
+
+
+
+
+
+ True
+ False
+ 6
+ 12
+
+
+ True
+ False
+ end
+ start
+ conference-symbolic
+ 6
+
+
+ True
+ True
+ 0
+
+
+
+
+ True
+ False
+ vertical
+ 6
+
+
+ True
+ False
+
+
+ True
+ False
+ Conference
+ 0
+
+
+
+
+
+ False
+ True
+ 0
+
+
+
+
+ True
+ True
+ True
+ Leave Conference
+
+
+ True
+ False
+ user-trash-symbolic
+
+
+
+
+
+ False
+ True
+ end
+ 1
+
+
+
+
+ False
+ True
+ 0
+
+
+
+
+ 450
+ True
+ False
+ none
+ False
+
+
+ True
+ True
+
+
+ True
+ False
+ 6
+ vertical
+ 6
+
+
+ True
+ False
+ Title:
+ True
+ 0
+
+
+
+
+
+ False
+ True
+ 0
+
+
+
+
+ True
+ True
+
+
+ False
+ True
+ 1
+
+
+
+
+ True
+ False
+
+
+ True
+ False
+ title_error
+ 0
+
+
+
+
+
+
+
+ False
+ True
+ 2
+
+
+
+
+
+
+
+
+ True
+ True
+
+
+ True
+ False
+ 6
+ vertical
+
+
+ True
+ False
+ 6
+
+
+ True
+ False
+ Show notifications
+ True
+ 0
+
+
+ False
+ True
+ 0
+
+
+
+
+ True
+ True
+
+
+ False
+ True
+ end
+ 1
+
+
+
+
+ False
+ True
+ 0
+
+
+
+
+ True
+ False
+ True
+
+
+ True
+ False
+ <small>Notifications have been globally disabled</small>
+ True
+ 0
+
+
+
+
+
+ False
+ True
+ 1
+
+
+
+
+
+
+
+
+
+ False
+ True
+ 1
+
+
+
+
+ Apply
+ True
+ True
+ True
+
+
+
+ False
+ True
+ 2
+
+
+
+
+ True
+ False
+ Peers
+ 0
+
+
+
+
+
+ False
+ True
+ 3
+
+
+
+
+ 300
+ True
+ False
+ none
+ False
+
+
+
+ False
+ True
+ 4
+
+
+
+
+ True
+ True
+ 1
+
+
+
+
+ True
+ False
+ vertical
+
+
+ True
+ True
+ 2
+
+
+
+
+
+
+
+
+
+
diff --git a/src/ui/conference_invite_entry.ui b/src/ui/conference_invite_entry.ui
new file mode 100644
index 0000000..80590d1
--- /dev/null
+++ b/src/ui/conference_invite_entry.ui
@@ -0,0 +1,169 @@
+
+
+
+
+
+
+
+
+ True
+ True
+
+
+ True
+ False
+ 6
+ 12
+
+
+ True
+ False
+ center
+ 24
+ friend-symbolic
+
+
+ False
+ True
+ 0
+
+
+
+
+ True
+ False
+ center
+ 6
+
+
+ True
+ False
+ vertical
+
+
+ True
+ False
+ Invite from:
+ True
+ 0
+
+
+
+
+
+ False
+ True
+ 0
+
+
+
+
+ True
+ False
+ contact_name
+ 0
+
+
+ False
+ True
+ 1
+
+
+
+
+ True
+ True
+ 1
+
+
+
+
+ True
+ False
+ center
+ 6
+
+
+ True
+ True
+ True
+ Accept invite
+
+
+ True
+ False
+ object-select-symbolic
+
+
+
+
+
+ False
+ True
+ 0
+
+
+
+
+ True
+ True
+ True
+ Reject invite
+
+
+ True
+ False
+ user-trash-symbolic
+
+
+
+
+
+ False
+ True
+ 1
+
+
+
+
+ False
+ True
+ 1
+
+
+
+
+ True
+ True
+ 1
+
+
+
+
+
+
diff --git a/src/ui/conference_window.ui b/src/ui/conference_window.ui
new file mode 100644
index 0000000..81d150c
--- /dev/null
+++ b/src/ui/conference_window.ui
@@ -0,0 +1,290 @@
+
+
+
+
+
+
+
+
+ True
+ False
+ vertical
+
+
+ True
+ True
+
+
+ True
+ False
+ none
+
+
+ True
+ False
+ none
+ False
+
+
+
+
+
+
+
+ True
+ True
+ 2
+
+
+
+
+ True
+ False
+
+
+ False
+ True
+ 3
+
+
+
+
+ True
+ False
+
+
+ True
+ True
+ never
+
+
+ True
+ True
+ 6
+ 6
+ 6
+ 6
+
+
+
+
+ True
+ True
+ 0
+
+
+
+
+ True
+ False
+ True
+ True
+ Insert Emoji
+ start
+ win.insert-smiley
+ none
+
+
+ True
+ False
+ face-smile-symbolic
+
+
+
+
+
+ False
+ True
+ 1
+
+
+
+
+ False
+ True
+ end
+ 4
+
+
+
+
+
+ True
+ False
+ center
+ center
+ 6
+ vertical
+ 6
+
+
+ True
+ False
+ face-surprise-symbolic
+ 1
+
+
+ False
+ True
+ 0
+
+
+
+
+ True
+ False
+ No one here...
+
+
+ False
+ True
+ 1
+
+
+
+
+
+ True
+ False
+ center
+ center
+ 6
+ vertical
+ 6
+
+
+ True
+ False
+ dialog-information-symbolic
+ 6
+
+
+ False
+ True
+ 0
+
+
+
+
+ True
+ False
+ No messages yet...
+
+
+ False
+ True
+ 1
+
+
+
+
+
+ False
+
+
+ True
+ True
+ 600
+ True
+ True
+
+
+ True
+ False
+ natural
+ natural
+ none
+
+
+ True
+ False
+ 6
+ vertical
+
+
+ True
+ False
+ none
+ False
+
+
+
+ False
+ True
+ 0
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/ui/contact_list.ui b/src/ui/contact_list.ui
deleted file mode 100644
index a05aef4..0000000
--- a/src/ui/contact_list.ui
+++ /dev/null
@@ -1,521 +0,0 @@
-
-
-
-
-
- 100
- 1
- 10
-
-
- True
- False
- gtk-missing-image
-
-
- True
- False
- gtk-missing-image
-
-
- True
- False
- gtk-missing-image
-
-
- True
- False
- gtk-missing-image
-
-
- True
- False
- gtk-missing-image
-
-
- True
- False
- gtk-copy
-
-
- True
- False
- gtk-edit
-
-
-
- True
- False
- gtk-missing-image
-
-
- True
- False
- gtk-missing-image
-
-
- True
- False
- gtk-missing-image
-
-
- True
- False
- gtk-missing-image
-
-
- True
- False
-
-
- 200
- True
- False
-
-
- True
- False
- vertical
-
-
- True
- False
- 16
-
-
- 44
- 41
- True
- False
- gtk-missing-image
-
-
- False
- True
- 0
-
-
-
-
- True
- False
- center
- vertical
-
-
- True
- False
- 0
- #username
- end
-
-
-
-
-
- False
- True
- 0
-
-
-
-
- True
- False
- 0
- #userstatus
- end
-
-
-
-
-
- False
- True
- 1
-
-
-
-
- True
- True
- 1
-
-
-
-
- True
- True
- True
-
-
- True
- False
-
-
- True
- False
- gtk-missing-image
-
-
- False
- True
- 0
-
-
-
-
- 26
- 26
- False
- True
- connecting...
-
-
- False
- True
- 1
-
-
-
-
-
-
-
- False
- True
- 2
-
-
-
-
- False
- True
- 0
-
-
-
-
- True
- False
-
-
- True
- False
-
-
- True
- False
- 3
- 3
- 3
- 3
- vertical
- adjustment1
-
-
- False
- True
- 0
-
-
-
-
- True
- False
- vertical
-
-
- 27
- True
- False
- start
- 5
- 1
- 0
-
-
-
- False
- True
- 0
-
-
-
-
- True
- True
- adjustment1
-
-
-
-
-
- True
- True
- 1
-
-
-
-
- True
- True
- 1
-
-
-
-
-
-
-
- True
- True
- 1
-
-
-
-
- 50
- True
- False
- True
-
-
- True
- True
- True
- Add contact
- image_add_contact
-
-
-
- False
- True
- 0
-
-
-
-
- True
- False
- True
- Create groupchat
- image_group_chat
-
-
-
- False
- True
- 1
-
-
-
-
- True
- True
- True
- image_filetransfer
-
-
-
- False
- True
- 2
-
-
-
-
- True
- True
- True
- Open preferences
- app.preferences
- image_preferences
-
-
-
- False
- True
- 3
-
-
-
-
- False
- True
- 2
-
-
-
-
-
-
-
- False
- False
-
-
-
-
- False
- True
- False
- False
-
-
- True
- False
-
-
-
-
diff --git a/src/ui/contact_list_entry.ui b/src/ui/contact_list_entry.ui
new file mode 100644
index 0000000..f0e0d52
--- /dev/null
+++ b/src/ui/contact_list_entry.ui
@@ -0,0 +1,115 @@
+
+
+
+
+
+
+
+
+ True
+ True
+
+
+ True
+ False
+ 6
+ 12
+
+
+ 44
+ 44
+ True
+ False
+ 48
+ friend-symbolic
+ 5
+
+
+
+ False
+ True
+ 0
+
+
+
+
+ True
+ False
+ vertical
+
+
+ True
+ False
+ contact_name
+ end
+ 0
+
+
+ False
+ True
+ 0
+
+
+
+
+ True
+ False
+ contact_status
+ end
+ 0
+
+
+
+ False
+ True
+ 1
+
+
+
+
+ False
+ True
+ 1
+
+
+
+
+ True
+ False
+ 26
+ offline-symbolic
+
+
+ False
+ True
+ end
+ 2
+
+
+
+
+
+
diff --git a/src/ui/contact_list_request_entry.ui b/src/ui/contact_list_request_entry.ui
new file mode 100644
index 0000000..1978ed5
--- /dev/null
+++ b/src/ui/contact_list_request_entry.ui
@@ -0,0 +1,101 @@
+
+
+
+
+
+
+
+
+ True
+ True
+
+
+ True
+ False
+ 6
+ 12
+
+
+ True
+ False
+ 48
+ contact-new-symbolic
+ 5
+
+
+
+ False
+ True
+ 0
+
+
+
+
+ True
+ False
+ center
+ vertical
+
+
+ True
+ False
+ contact_name
+ end
+ 0
+
+
+ False
+ True
+ 0
+
+
+
+
+ True
+ False
+ contact_status
+ end
+ 0
+
+
+
+ False
+ True
+ 1
+
+
+
+
+ False
+ True
+ 1
+
+
+
+
+
+
diff --git a/src/ui/contact_list_widget.ui b/src/ui/contact_list_widget.ui
new file mode 100644
index 0000000..4482640
--- /dev/null
+++ b/src/ui/contact_list_widget.ui
@@ -0,0 +1,541 @@
+
+
+
+
+
+
+
+
+ True
+ False
+ 26
+ offline
+
+
+ True
+ False
+ end
+ 12
+ 6
+ 6
+
+
+ True
+ False
+ pan-down-symbolic
+
+
+ False
+ True
+ 0
+
+
+
+
+ True
+ False
+ Add a friend
+ end
+
+
+ False
+ True
+ 1
+
+
+
+
+
+ False
+ 6
+
+
+ True
+ True
+ edit-find-symbolic
+ False
+ False
+
+
+
+
+ 200
+ True
+ False
+ vertical
+
+
+ True
+ False
+ vertical
+
+
+ True
+ False
+ slide-up
+
+
+ True
+ True
+ True
+ win.add_contact
+
+
+ True
+ False
+ 6
+
+
+ True
+ False
+ dialog-information-symbolic
+
+
+ False
+ True
+ 0
+
+
+
+
+ True
+ False
+ friend_request_label
+ end
+ 0
+
+
+ False
+ True
+ 1
+
+
+
+
+
+
+
+
+
+ False
+ True
+ end
+ 0
+
+
+
+
+ True
+ False
+ slide-up
+
+
+ True
+ True
+ True
+ win.groupchats
+ True
+
+
+ True
+ False
+ 6
+
+
+ True
+ False
+ dialog-information-symbolic
+
+
+ False
+ True
+ 0
+
+
+
+
+ True
+ False
+ conference_invite_label
+ end
+ 0
+
+
+ False
+ True
+ 1
+
+
+
+
+
+
+
+
+
+ False
+ True
+ end
+ 1
+
+
+
+
+ False
+ True
+
+
+
+ False
+ True
+ 0
+
+
+
+
+
+ False
+ True
+ end
+ 1
+
+
+
+
+ False
+ True
+ 2
+
+
+
+
+ False
+ True
+
+
+ False
+ True
+ 3
+
+
+
+
+ True
+ True
+ never
+
+
+ True
+ False
+
+
+ True
+ False
+
+
+
+
+
+
+
+ True
+ True
+ 4
+
+
+
+
+ True
+ False
+
+
+ False
+ True
+ 5
+
+
+
+
+ True
+ True
+ 1
+
+
+
+
+ True
+ False
+ True
+
+
+ True
+ True
+ False
+ Add a contact
+ win.add_contact
+ none
+
+
+ True
+ False
+ contact-new-symbolic
+
+
+
+
+
+ False
+ True
+ 0
+
+
+
+
+ True
+ True
+ False
+ Create a conference
+ win.groupchats
+ none
+
+
+ True
+ False
+ conference-symbolic
+
+
+
+
+
+ False
+ True
+ 1
+
+
+
+
+ True
+ True
+ False
+ View file transfers
+ win.filetransfer
+ none
+
+
+ True
+ False
+ network-transmit-receive-symbolic
+
+
+
+
+
+ False
+ True
+ 2
+
+
+
+
+ True
+ True
+ False
+ Open settings
+ app.preferences
+ none
+
+
+ True
+ False
+ preferences-system-symbolic
+
+
+
+
+
+ False
+ True
+ 3
+
+
+
+
+ False
+ True
+ 2
+
+
+
+
+
+ True
+ False
+
+
+ True
+ True
+ True
+ Edit your profile
+ win.show_user
+
+
+ True
+ False
+ 22
+ friend-symbolic
+
+
+
+
+
+
+ False
+ True
+ 0
+
+
+
+
+
+ False
+ True
+ end
+ 1
+
+
+
+
+ True
+ False
+ center
+ vertical
+
+
+ True
+ False
+ username
+ end
+ 1
+ 0
+
+
+
+ True
+ True
+ 0
+
+
+
+
+ True
+ False
+ statusmessage
+ end
+ 1
+ 0
+
+
+
+ True
+ True
+ 1
+
+
+
+
+ True
+ True
+ 2
+
+
+
+
diff --git a/src/ui/conversation_window.ui b/src/ui/conversation_window.ui
index b670738..bf533c5 100644
--- a/src/ui/conversation_window.ui
+++ b/src/ui/conversation_window.ui
@@ -1,368 +1,368 @@
-
-
-
-
- True
- False
- gtk-missing-image
-
-
- True
- False
- gtk-missing-image
-
-
- True
+
+
+
+
+
+
+
-
+
-
+
True
False
- gtk-missing-image
+ center
+ center
+ 6
+ vertical
+ 6
+
+
+ True
+ False
+ dialog-information-symbolic
+ 6
+
+
+ False
+ True
+ 0
+
+
+
+
+ True
+ False
+ No messages yet...
+
+
+ False
+ True
+ 1
+
+
+
-
- True
+
False
- vertical
-
- 72
+
True
False
+ 6
+ 6
-
+
True
- False
- 10
- True
- 6
+ False
+ True
+ True
+ Attach screenshot…
+ win.insert-screenshot
-
- 44
- 41
+
True
False
- center
- gtk-missing-image
+ insert-image-symbolic
-
- False
- True
- 0
-
+
+
+
+ False
+ True
+ 0
+
+
+
+
+ True
+ False
+ True
+ True
+ Attach file…
+ win.insert-file
-
+
True
False
- center
- 8
- vertical
-
-
- True
- False
-
-
- True
- False
- 0
- #name
- True
- end
-
-
- False
- True
- 0
-
-
-
-
- True
- True
- True
- none
-
-
- True
- False
- down
-
-
-
-
- False
- True
- 1
-
-
-
-
- False
- True
- 0
-
-
-
-
- True
- False
- 0
- #Statusmessage
- True
- end
-
-
- False
- True
- 1
-
-
+ insert-object-symbolic
-
- True
- True
- 1
-
+
False
True
- 0
+ 1
+
+
+
+
+ True
+ False
+ vertical
+
+
+ True
+ False
-
+
True
- False
- 8
- 12
- True
-
-
- 64
- True
- True
- True
- Call contact
- image_call
-
-
-
- False
- True
- 1
-
-
+ True
-
- 64
- True
- True
- True
- Call contact with video
- image_call_video
-
+
+ True
+ False
+ none
+
+
+ True
+ False
+ none
+ False
+
+
+
-
- False
- True
- 2
-
- False
- True
- end
- 1
+ -1
- False
+ True
True
- 0
+ 2
-
+
True
False
False
True
- 1
+ 3
-
+
True
- True
- vertical
- 2147483647
- True
+ False
-
-
+
True
False
- 12
- 12
+ start
-
+
True
- False
-
-
- True
- True
- in
- 0
-
-
-
-
-
- True
- True
- 0
-
-
+ False
+ True
+ True
+ Insert Emoji
+ win.insert-smiley
+ none
-
+
True
False
- vertical
- 2
- True
-
-
- True
- False
- True
- True
- Insert Smiley
- image_insert_smiley
-
-
-
- True
- True
- 0
-
-
-
-
- True
- False
- True
- True
- Send file
- image_send_file
-
-
-
- True
- True
- 1
-
-
+ face-smile-symbolic
-
- False
- True
- 1
-
+
- True
+ False
True
0
-
- False
- 76
+
False
True
- end
1
- False
- False
+ False
+ True
+ 1
- True
+ False
True
- 2
+ 4
+
+
+ True
+ False
+ end
+ end
+ 6
+ slide-up
+ True
+
+
+ True
+ False
+ typing_label
+
+
diff --git a/src/ui/create_groupchat_widget.ui b/src/ui/create_groupchat_widget.ui
new file mode 100644
index 0000000..cd79edb
--- /dev/null
+++ b/src/ui/create_groupchat_widget.ui
@@ -0,0 +1,420 @@
+
+
+
+
+
+
+
+
+ True
+ False
+ 6
+ 12
+
+
+ True
+ False
+ end
+ start
+ conference-symbolic
+ 6
+
+
+ True
+ True
+ 0
+
+
+
+
+ True
+ False
+ vertical
+ 6
+
+
+ True
+ False
+ crossfade
+
+
+ True
+ False
+ vertical
+ 6
+
+
+ True
+ False
+ Create a conference
+ 0
+
+
+
+
+
+ False
+ True
+ 0
+
+
+
+
+ 400
+ True
+ False
+ none
+ False
+
+
+ True
+ True
+
+
+ True
+ False
+ 6
+ vertical
+ 6
+
+
+ True
+ False
+ _Title:
+ True
+ 0
+
+
+
+
+
+ False
+ True
+ 0
+
+
+
+
+ True
+ True
+ True
+ True
+ Conference
+ paste from clipboard
+
+
+ False
+ True
+ 1
+
+
+
+
+ True
+ False
+
+
+ True
+ False
+ title_error
+ 0
+
+
+
+
+
+
+
+ False
+ True
+ 2
+
+
+
+
+ True
+ False
+ <small>Name the conference (optional)</small>
+ True
+ 0
+
+
+
+ False
+ True
+ 3
+
+
+
+
+
+
+
+
+ True
+ True
+
+
+ True
+ False
+ 6
+ vertical
+ 6
+
+
+ True
+ False
+ T_ype:
+ True
+ 0
+
+
+
+
+
+ False
+ True
+ 0
+
+
+
+
+ True
+ False
+ True
+
+
+ True
+ True
+ widget.conference-type
+ 'text'
+ Text
+ True
+ True
+
+
+ False
+ True
+ 0
+
+
+
+
+ True
+ True
+ widget.conference-type
+ 'speech'
+ Speech
+ True
+ True
+
+
+ False
+ True
+ 1
+
+
+
+
+
+ False
+ True
+ 1
+
+
+
+
+ True
+ False
+ <small>Select a conference type</small>
+ True
+ 0
+
+
+
+ False
+ True
+ 2
+
+
+
+
+
+
+
+
+
+ False
+ True
+ 1
+
+
+
+
+ Create
+ True
+ True
+ True
+
+
+
+ False
+ True
+ 2
+
+
+
+
+ page0
+ New conference
+
+
+
+
+ True
+ False
+ vertical
+ 6
+
+
+ True
+ False
+ Conference invites
+ 0
+
+
+
+
+
+ False
+ True
+ 0
+
+
+
+
+ 450
+ 350
+ True
+ False
+ none
+ False
+
+
+
+ True
+ True
+ 1
+
+
+
+
+ page1
+ Conference invites
+ 1
+
+
+
+
+ False
+ True
+ 1
+
+
+
+
+ True
+ True
+ 1
+
+
+
+
+ True
+ False
+ vertical
+
+
+ True
+ True
+ 2
+
+
+
+
+ True
+ False
+ center
+ stack
+
+
+ True
+ False
+ center
+ center
+ 6
+ vertical
+ 6
+
+
+ True
+ False
+ conference-symbolic
+ 6
+
+
+ False
+ True
+ 0
+
+
+
+
+ True
+ False
+ No new conference invites
+
+
+ False
+ True
+ 1
+
+
+
+
+
diff --git a/src/ui/custom.css b/src/ui/custom.css
new file mode 100644
index 0000000..11f08b5
--- /dev/null
+++ b/src/ui/custom.css
@@ -0,0 +1,67 @@
+/*
+ * custom.css
+ *
+ * Copyright (C) 2018 Venom authors and contributors
+ *
+ * This file is part of Venom.
+ *
+ * Venom is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Venom is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Venom. If not, see .
+ */
+
+.avatar {
+ background: alpha(@theme_bg_color, .3);
+ border-radius: 10%;
+}
+
+@keyframes welcome-highlight {
+ 0% { -gtk-icon-shadow: 0px 0px 0px alpha(@theme_fg_color, .55);}
+ 50% { -gtk-icon-shadow: 0px 0px 0px alpha(@theme_fg_color, .55);}
+ 100% { -gtk-icon-shadow: 0px 0px 24px alpha(@theme_fg_color, 0); }
+}
+
+.welcome-highlight {
+ animation: welcome-highlight 4s infinite ease-in;
+}
+
+@keyframes pulse {
+ 0% {
+ opacity: 0.2;
+ -gtk-icon-transform: scale(1);
+ }
+ 50% {
+ opacity: 1.0;
+ -gtk-icon-transform: scale(1.1);
+ }
+ 100% {
+ opacity: 0.2;
+ -gtk-icon-transform: scale(1);
+ }
+}
+
+.highlight {
+ animation: pulse 2s infinite ease-out;
+}
+
+.conversation row {
+ box-shadow: 0px 1px 2px 1px alpha(black, 0.2);
+ margin: 1px 6px 3px 6px;
+}
+
+.separated row {
+ border-bottom: 1px solid @theme_bg_color;
+}
+
+headerbar:first-child {
+ padding-right: 0px
+}
diff --git a/src/ui/file_transfer_entry.ui b/src/ui/file_transfer_entry.ui
new file mode 100644
index 0000000..bb7df72
--- /dev/null
+++ b/src/ui/file_transfer_entry.ui
@@ -0,0 +1,220 @@
+
+
+
+
+
+
+
+
+ True
+ True
+
+
+ True
+ False
+ 6
+ 12
+
+
+ True
+ False
+ open-menu-symbolic
+
+
+
+ False
+ True
+ 0
+
+
+
+
+ True
+ True
+ True
+ Remove transfer
+ center
+
+
+ True
+ False
+ user-trash-symbolic
+
+
+
+
+
+ False
+ True
+ end
+ 1
+
+
+
+
+ True
+ False
+ center
+ vertical
+ 6
+
+
+ True
+ False
+ description
+ end
+ 0
+
+
+ False
+ True
+ 0
+
+
+
+
+ True
+ False
+
+
+ False
+ True
+ 1
+
+
+
+
+ True
+ True
+ 3
+
+
+
+
+ True
+ False
+
+
+ True
+ True
+ True
+ Open file
+ center
+
+
+ True
+ False
+ document-open-symbolic
+
+
+
+
+
+ False
+ True
+ 0
+
+
+
+
+ True
+ True
+ True
+ Start transfer
+ center
+
+
+ True
+ False
+ media-playback-start-symbolic
+
+
+
+
+ False
+ True
+ 1
+
+
+
+
+ True
+ True
+ True
+ Pause transfer
+ center
+
+
+ True
+ False
+ media-playback-pause-symbolic
+
+
+
+
+ False
+ True
+ 2
+
+
+
+
+ True
+ True
+ True
+ Stop transfer
+ center
+
+
+ True
+ False
+ media-playback-stop-symbolic
+
+
+
+
+ False
+ True
+ 3
+
+
+
+
+
+ False
+ True
+ end
+ 4
+
+
+
+
+
+
diff --git a/src/ui/file_transfer_entry_inline.ui b/src/ui/file_transfer_entry_inline.ui
new file mode 100644
index 0000000..73a7253
--- /dev/null
+++ b/src/ui/file_transfer_entry_inline.ui
@@ -0,0 +1,249 @@
+
+
+
+
+
+
+
+
+ True
+ True
+ False
+ False
+
+
+ True
+ False
+
+
+ True
+ False
+ vertical
+
+
+
+
+
+ True
+ True
+ 0
+
+
+
+
+ True
+ False
+ 6
+ 12
+
+
+ True
+ True
+ True
+ Remove transfer
+ center
+
+
+ True
+ False
+ user-trash-symbolic
+
+
+
+
+
+ False
+ True
+ end
+ 1
+
+
+
+
+ True
+ False
+ center
+ vertical
+ 6
+
+
+ True
+ False
+ description
+ end
+ 0
+
+
+ False
+ True
+ 0
+
+
+
+
+ True
+ False
+
+
+ False
+ True
+ 1
+
+
+
+
+ True
+ True
+ 3
+
+
+
+
+ True
+ False
+
+
+ True
+ True
+ True
+ Open file
+ center
+
+
+ True
+ False
+ document-open-symbolic
+
+
+
+
+
+ False
+ True
+ 0
+
+
+
+
+ True
+ True
+ True
+ Start transfer
+ center
+
+
+ True
+ False
+ media-playback-start-symbolic
+
+
+
+
+ False
+ True
+ 1
+
+
+
+
+ True
+ True
+ True
+ Pause transfer
+ center
+
+
+ True
+ False
+ media-playback-pause-symbolic
+
+
+
+
+ False
+ True
+ 2
+
+
+
+
+ True
+ True
+ True
+ Stop transfer
+ center
+
+
+ True
+ False
+ media-playback-stop-symbolic
+
+
+
+
+ False
+ True
+ 3
+
+
+
+
+
+ False
+ True
+ end
+ 4
+
+
+
+
+ True
+ True
+ 1
+
+
+
+
+ True
+ False
+ vertical
+
+
+
+
+
+ True
+ True
+ end
+ 2
+
+
+
+
+
+
diff --git a/src/ui/file_transfer_widget.ui b/src/ui/file_transfer_widget.ui
new file mode 100644
index 0000000..05828b7
--- /dev/null
+++ b/src/ui/file_transfer_widget.ui
@@ -0,0 +1,152 @@
+
+
+
+
+
+
+
+
+ True
+ False
+ 6
+ 12
+
+
+ True
+ False
+ end
+ start
+ network-transmit-receive-symbolic
+ 6
+
+
+ True
+ True
+ 0
+
+
+
+
+ True
+ False
+ vertical
+ 6
+
+
+ True
+ False
+ File transfers
+ 0
+
+
+
+
+
+ False
+ True
+ 0
+
+
+
+
+ 450
+ 300
+ True
+ False
+ none
+
+
+
+ False
+ True
+ 1
+
+
+
+
+ True
+ True
+ 1
+
+
+
+
+ True
+ False
+ vertical
+
+
+
+
+
+
+
+
+
+
+
+ True
+ True
+ 2
+
+
+
+
+ True
+ False
+ center
+ center
+ vertical
+ 6
+
+
+ True
+ False
+ document-save-symbolic
+ 6
+
+
+ False
+ True
+ 0
+
+
+
+
+ True
+ False
+ No file transfers yet …
+
+
+ False
+ True
+ 1
+
+
+
+
+
diff --git a/src/ui/friend_info_widget.ui b/src/ui/friend_info_widget.ui
new file mode 100644
index 0000000..34f09c5
--- /dev/null
+++ b/src/ui/friend_info_widget.ui
@@ -0,0 +1,649 @@
+
+
+
+
+
+
+
+
+ True
+ False
+ 6
+
+
+ True
+ False
+ vertical
+
+
+
+
+
+
+
+
+
+
+
+ True
+ True
+ 0
+
+
+
+
+ True
+ False
+ vertical
+ 6
+
+
+ True
+ False
+ vertical
+ 6
+
+
+ True
+ False
+
+
+ True
+ False
+ 6
+
+
+ True
+ False
+ start
+ 128
+ friend-symbolic
+ 0
+
+
+ False
+ True
+ 0
+
+
+
+
+ True
+ False
+ end
+ vertical
+
+
+ True
+ False
+ start
+ username
+ True
+ end
+ 0
+
+
+
+
+
+
+ False
+ True
+ 0
+
+
+
+
+ True
+ False
+ start
+ statusmessage
+ True
+ end
+ 0
+
+
+
+
+
+
+ False
+ True
+ 1
+
+
+
+
+ True
+ False
+ start
+ last_seen
+ True
+ end
+ 0
+
+
+ False
+ True
+ 2
+
+
+
+
+ False
+ True
+ 1
+
+
+
+
+ False
+ True
+ 0
+
+
+
+
+ True
+ True
+ True
+ Remove from your friends list
+ start
+ start
+
+
+ True
+ False
+ user-trash-symbolic
+
+
+
+
+
+ False
+ True
+ end
+ 1
+
+
+
+
+ False
+ True
+ 0
+
+
+
+
+ 400
+ True
+ False
+ none
+ False
+
+
+ True
+ True
+
+
+ True
+ False
+ 6
+ vertical
+ 6
+
+
+ True
+ False
+ Alias:
+ end
+ 0
+
+
+
+
+
+ False
+ True
+ 0
+
+
+
+
+ True
+ True
+ alias
+ True
+ edit-clear-all-symbolic
+ Reset alias
+
+
+ False
+ True
+ 1
+
+
+
+
+ True
+ False
+ <small>Set a custom alias to quickly find your friends</small>
+ True
+ end
+ 0
+
+
+
+ False
+ True
+ 2
+
+
+
+
+
+
+
+
+ True
+ True
+
+
+ True
+ False
+ 6
+ vertical
+
+
+ True
+ False
+ 6
+
+
+ True
+ False
+ Show notifications
+ True
+ end
+ 0
+
+
+ False
+ True
+ 0
+
+
+
+
+ True
+ True
+
+
+ False
+ True
+ end
+ 1
+
+
+
+
+ False
+ True
+ 0
+
+
+
+
+ True
+ False
+ True
+
+
+ True
+ False
+ <small>Notifications have been globally disabled</small>
+ True
+ end
+ 0
+
+
+
+
+
+ False
+ True
+ 1
+
+
+
+
+
+
+
+
+ True
+ True
+
+
+ True
+ False
+ 6
+ 6
+
+
+ True
+ False
+ Auto accept conference invites
+ True
+ end
+ 0
+
+
+ False
+ True
+ 0
+
+
+
+
+ True
+ True
+
+
+ False
+ True
+ end
+ 1
+
+
+
+
+
+
+
+
+ True
+ True
+
+
+ True
+ False
+ 6
+ vertical
+ 6
+
+
+ True
+ False
+ 6
+
+
+ True
+ False
+ Auto accept file transfers
+ True
+ end
+ 0
+
+
+ False
+ True
+ 0
+
+
+
+
+ True
+ True
+
+
+ False
+ True
+ end
+ 1
+
+
+
+
+ False
+ True
+ 0
+
+
+
+
+ True
+ False
+ True
+
+
+ True
+ False
+ 6
+
+
+ True
+ False
+ Save files to
+ end
+ 0
+
+
+ False
+ True
+ 0
+
+
+
+
+ True
+ False
+ select-folder
+
+
+
+ False
+ True
+ end
+ 1
+
+
+
+
+
+
+ False
+ True
+ 1
+
+
+
+
+
+
+
+
+
+ False
+ True
+ 1
+
+
+
+
+ False
+ True
+ 0
+
+
+
+
+ True
+ False
+ vertical
+ 6
+
+
+ True
+ False
+ Tox
+ end
+ 0
+
+
+
+
+
+ False
+ True
+ 0
+
+
+
+
+ True
+ False
+ none
+ False
+
+
+ True
+ True
+
+
+ True
+ False
+ 6
+ vertical
+ 6
+
+
+ True
+ False
+ Public key:
+ True
+ end
+ 0
+
+
+
+
+
+ False
+ True
+ 0
+
+
+
+
+ True
+ False
+ ##################
+ True
+ end
+ 0
+
+
+
+ False
+ True
+ 1
+
+
+
+
+
+
+
+
+
+ False
+ True
+ 1
+
+
+
+
+ False
+ True
+ 1
+
+
+
+
+ Apply
+ True
+ True
+ True
+
+
+
+ False
+ True
+ 2
+
+
+
+
+ True
+ True
+ 1
+
+
+
+
+ True
+ False
+ vertical
+
+
+ True
+ True
+ 2
+
+
+
+
+
+
+
+
+
+
diff --git a/src/ui/friend_request_widget.ui b/src/ui/friend_request_widget.ui
new file mode 100644
index 0000000..c4c6fe5
--- /dev/null
+++ b/src/ui/friend_request_widget.ui
@@ -0,0 +1,228 @@
+
+
+
+
+
+
+
+
+ True
+ True
+
+
+ True
+ False
+ 6
+ 12
+
+
+ True
+ False
+ end
+ start
+ 44
+ friend-symbolic
+
+
+ False
+ True
+ 0
+
+
+
+
+ True
+ False
+ 6
+
+
+ True
+ False
+ vertical
+ 6
+
+
+ True
+ False
+ _Public key:
+ True
+ 0
+
+
+
+
+
+ False
+ True
+ 0
+
+
+
+
+ True
+ False
+ contact_id
+ True
+ 0
+
+
+
+ False
+ True
+ 1
+
+
+
+
+ True
+ False
+ _Message:
+ True
+ 0
+
+
+
+
+
+ False
+ True
+ 2
+
+
+
+
+ 100
+ True
+ False
+ vertical
+
+
+ True
+ False
+ 6
+ 6
+ 6
+ 6
+ contact_message
+ True
+ word-char
+ 0
+ 0
+
+
+ True
+ True
+ 0
+
+
+
+
+
+ True
+ True
+ 3
+
+
+
+
+ True
+ True
+ 1
+
+
+
+
+ True
+ False
+ vertical
+ 6
+
+
+ True
+ True
+ True
+ Reject request
+
+
+ True
+ False
+ user-trash-symbolic
+
+
+
+
+
+ False
+ True
+ 0
+
+
+
+
+ True
+ True
+ True
+ Accept request
+
+
+ True
+ False
+ object-select-symbolic
+
+
+
+
+
+ False
+ True
+ 1
+
+
+
+
+ False
+ True
+ 1
+
+
+
+
+ True
+ True
+ 1
+
+
+
+
+
+
diff --git a/src/ui/message_widget.ui b/src/ui/message_widget.ui
new file mode 100644
index 0000000..cc7408e
--- /dev/null
+++ b/src/ui/message_widget.ui
@@ -0,0 +1,177 @@
+
+
+
+
+
+
+
+
+ True
+ True
+
+
+ True
+ False
+ 6
+
+
+ True
+ False
+ start
+ 44
+ user-info-symbolic
+ 6
+
+
+
+ False
+ True
+ 0
+
+
+
+
+ True
+ False
+ vertical
+
+
+ True
+ False
+
+
+ True
+ False
+ sender
+ True
+ end
+ 0
+
+
+ False
+ True
+ 0
+
+
+
+
+ True
+ False
+ 6
+ slide-right
+ 125
+
+
+ True
+ False
+ timestamp
+
+
+
+
+
+ False
+ True
+ 1
+
+
+
+
+ True
+ False
+ 6
+
+
+ False
+ True
+ Message sent ✓
+ object-select-symbolic
+
+
+
+ False
+ True
+ 0
+
+
+
+
+ False
+ True
+ Message received ✓
+ object-select-symbolic
+
+
+ False
+ True
+ 1
+
+
+
+
+ False
+ True
+ 2
+
+
+
+
+ False
+ True
+ 0
+
+
+
+
+ True
+ False
+ start
+ message
+ True
+ True
+ word-char
+ True
+ 0
+
+
+ False
+ True
+ 1
+
+
+
+
+ True
+ True
+ 1
+
+
+
+
+
+
diff --git a/src/ui/node_widget.ui b/src/ui/node_widget.ui
new file mode 100644
index 0000000..6e5b878
--- /dev/null
+++ b/src/ui/node_widget.ui
@@ -0,0 +1,127 @@
+
+
+
+
+
+
+
+
+ True
+ True
+
+
+ True
+ False
+ 6
+ 12
+
+
+ True
+ False
+ vertical
+
+
+ True
+ False
+ host:port
+ end
+ 0
+
+
+ False
+ True
+ 0
+
+
+
+
+ True
+ False
+ maintainer
+ end
+ 0
+
+
+
+ False
+ True
+ 1
+
+
+
+
+ False
+ True
+ 0
+
+
+
+
+ True
+ True
+ center
+
+
+ False
+ True
+ end
+ 1
+
+
+
+
+ True
+ False
+ location
+
+
+ False
+ True
+ end
+ 2
+
+
+
+
+ True
+ False
+ public_key
+ True
+ 76
+ 0
+
+
+
+ False
+ True
+ end
+ 3
+
+
+
+
+
+
diff --git a/src/ui/peer_entry.ui b/src/ui/peer_entry.ui
new file mode 100644
index 0000000..6d341ca
--- /dev/null
+++ b/src/ui/peer_entry.ui
@@ -0,0 +1,133 @@
+
+
+
+
+
+
+
+
+ True
+ True
+
+
+ True
+ False
+ 6
+ 6
+
+
+ True
+ False
+ friend-symbolic
+ 5
+
+
+ False
+ True
+ 0
+
+
+
+
+ True
+ False
+ center
+ vertical
+
+
+ True
+ False
+ 6
+
+
+ True
+ False
+ peer_name
+ 0
+
+
+ False
+ True
+ 0
+
+
+
+
+ False
+ True
+ This peer is also in your friends list
+ starred-symbolic
+
+
+ False
+ True
+ 1
+
+
+
+
+ False
+ True
+ That's you
+ avatar-default-symbolic
+
+
+ False
+ True
+ 2
+
+
+
+
+ False
+ True
+ 0
+
+
+
+
+ True
+ False
+ peer_key
+ 0
+
+
+
+ False
+ True
+ 1
+
+
+
+
+ True
+ True
+ 1
+
+
+
+
+
+
diff --git a/src/ui/peer_entry_compact.ui b/src/ui/peer_entry_compact.ui
new file mode 100644
index 0000000..acd7603
--- /dev/null
+++ b/src/ui/peer_entry_compact.ui
@@ -0,0 +1,79 @@
+
+
+
+
+
+
+
+
+ True
+ True
+
+
+ True
+ False
+ 6
+
+
+ False
+ True
+ That's you
+ avatar-default-symbolic
+
+
+ False
+ True
+ end
+ 0
+
+
+
+
+ False
+ True
+ This peer is also in your friends list
+ starred-symbolic
+
+
+ False
+ True
+ end
+ 1
+
+
+
+
+ True
+ False
+ peer_name
+ 0
+
+
+ False
+ True
+ 2
+
+
+
+
+
+
diff --git a/src/ui/settings_widget.ui b/src/ui/settings_widget.ui
new file mode 100644
index 0000000..a556cd8
--- /dev/null
+++ b/src/ui/settings_widget.ui
@@ -0,0 +1,1828 @@
+
+
+
+
+
+
+
+
+ 365
+ 180
+ 1
+ 10
+
+
+ 65535
+ 1
+ 10
+
+
+ True
+ False
+
+
+ True
+ False
+
+
+
+ False
+ True
+ 0
+
+
+
+
+ True
+ False
+
+
+ False
+ True
+ 1
+
+
+
+
+ True
+ False
+ 125
+ crossfade
+
+
+ True
+ True
+
+
+ True
+ False
+ 6
+ none
+
+
+ True
+ False
+ start
+ 12
+ 12
+ none
+ False
+
+
+ True
+ False
+ start
+
+
+ True
+ False
+ vertical
+ 6
+
+
+ True
+ False
+ 6
+
+
+ True
+ False
+ preferences-desktop-wallpaper-symbolic
+
+
+ False
+ True
+ 0
+
+
+
+
+ True
+ False
+ Appearance
+ 0
+
+
+
+
+
+ False
+ True
+ 1
+
+
+
+
+ False
+ True
+ 0
+
+
+
+
+ 450
+ True
+ False
+ none
+
+
+ True
+ True
+
+
+ True
+ False
+ 6
+ 6
+
+
+ True
+ False
+ center
+ vertical
+
+
+ True
+ False
+ Dark Theme
+ 0
+
+
+ False
+ True
+ 0
+
+
+
+
+ True
+ False
+ <small>Use a dark variant of the theme</small>
+ True
+ 0
+
+
+
+ False
+ True
+ 1
+
+
+
+
+ True
+ True
+ 0
+
+
+
+
+ True
+ True
+ center
+
+
+ False
+ True
+ end
+ 1
+
+
+
+
+
+
+
+
+ True
+ True
+
+
+ True
+ False
+ 6
+ 6
+
+
+ True
+ False
+ center
+ vertical
+
+
+ True
+ False
+ Animations
+ 0
+
+
+ False
+ True
+ 0
+
+
+
+
+ True
+ False
+ <small>Enable animated transitions</small>
+ True
+ 0
+
+
+
+ False
+ True
+ 1
+
+
+
+
+ True
+ True
+ 0
+
+
+
+
+ True
+ True
+ center
+
+
+ False
+ True
+ end
+ 1
+
+
+
+
+
+
+
+
+ True
+ True
+
+
+ True
+ False
+ 6
+ 6
+
+
+ True
+ False
+ center
+ vertical
+
+
+ True
+ False
+ Notifications
+ 0
+
+
+ False
+ True
+ 0
+
+
+
+
+ True
+ False
+ <small>Show notifications for unread messages</small>
+ True
+ 0
+
+
+
+ False
+ True
+ 1
+
+
+
+
+ True
+ True
+ 0
+
+
+
+
+ True
+ True
+ center
+
+
+ False
+ True
+ end
+ 1
+
+
+
+
+
+
+
+
+ True
+ True
+
+
+ True
+ False
+ 6
+ 6
+
+
+ True
+ False
+ center
+ vertical
+
+
+ True
+ False
+ Minimize to tray
+ 0
+
+
+ False
+ True
+ 0
+
+
+
+
+ True
+ False
+ <small>Minimize app to system tray on close</small>
+ True
+ 0
+
+
+
+ False
+ True
+ 1
+
+
+
+
+ True
+ True
+ 0
+
+
+
+
+ True
+ True
+ center
+
+
+ False
+ True
+ end
+ 1
+
+
+
+
+
+
+
+
+
+ False
+ True
+ 1
+
+
+
+
+
+
+
+
+ True
+ False
+ start
+
+
+ True
+ False
+ vertical
+ 6
+
+
+ True
+ False
+ 6
+
+
+ True
+ False
+ preferences-system-privacy-symbolic
+
+
+ False
+ True
+ 0
+
+
+
+
+ True
+ False
+ Privacy
+ 0
+
+
+
+
+
+ False
+ True
+ 1
+
+
+
+
+ False
+ True
+ 0
+
+
+
+
+ True
+ False
+ none
+
+
+ True
+ True
+
+
+ True
+ False
+ 6
+ 6
+
+
+ True
+ False
+ center
+ vertical
+
+
+ True
+ False
+ Send typing notifications
+ 0
+
+
+ False
+ True
+ 0
+
+
+
+
+ True
+ False
+ <small>Show others when I am typing</small>
+ True
+ 0
+
+
+
+ False
+ True
+ 1
+
+
+
+
+ False
+ True
+ 0
+
+
+
+
+ True
+ True
+ center
+
+
+ False
+ True
+ end
+ 1
+
+
+
+
+
+
+
+
+
+ False
+ True
+ 1
+
+
+
+
+
+
+
+
+ True
+ False
+ start
+
+
+ True
+ False
+ vertical
+ 6
+
+
+ True
+ False
+ 6
+
+
+ True
+ False
+ system-search-symbolic
+
+
+ False
+ True
+ 0
+
+
+
+
+ True
+ False
+ History
+
+
+
+
+
+ False
+ True
+ 1
+
+
+
+
+ True
+ False
+ True
+ center
+
+
+ False
+ True
+ end
+ 2
+
+
+
+
+ False
+ True
+ 0
+
+
+
+
+ True
+ False
+ slide-up
+ True
+
+
+ True
+ False
+ none
+
+
+ True
+ True
+
+
+ True
+ False
+ 6
+ vertical
+
+
+ True
+ True
+ False
+ True
+ history_delete_radio
+
+
+ True
+ False
+ 6
+ Keep forever
+ 0
+
+
+
+
+ False
+ True
+ 0
+
+
+
+
+
+
+
+
+ True
+ True
+
+
+ True
+ False
+ 6
+ 6
+
+
+ True
+ True
+ False
+ True
+ True
+
+
+ True
+ False
+ 6
+ Remove older than
+ 0
+
+
+
+
+ False
+ True
+ 0
+
+
+
+
+ True
+ True
+ 5
+ digits
+ history_delete_adjustment
+ True
+ True
+ if-valid
+ 180
+
+
+ False
+ True
+ 1
+
+
+
+
+ True
+ False
+ days
+
+
+ False
+ True
+ 2
+
+
+
+
+
+
+
+
+
+
+
+ False
+ True
+ 1
+
+
+
+
+ True
+ False
+ True
+ True
+ Delete all previous conversations
+
+
+ True
+ False
+ user-trash-symbolic
+
+
+
+
+
+ False
+ True
+ 2
+
+
+
+
+
+
+
+
+
+
+
+
+ page0
+ page0
+
+
+
+
+ True
+ True
+
+
+ True
+ False
+ 6
+ none
+
+
+ True
+ False
+
+
+ True
+ False
+ vertical
+
+
+
+
+
+
+
+
+
+
+
+ True
+ True
+ 0
+
+
+
+
+ True
+ False
+ vertical
+ 6
+
+
+ True
+ False
+ 6
+
+
+ True
+ False
+ venom-symbolic
+
+
+ False
+ True
+ 1
+
+
+
+
+ True
+ False
+ <b>Connection</b>
+ True
+ 0
+
+
+ False
+ True
+ 2
+
+
+
+
+ False
+ True
+ 0
+
+
+
+
+ 450
+ True
+ False
+ none
+
+
+ True
+ True
+
+
+ True
+ False
+ 6
+ 6
+
+
+ True
+ False
+ center
+ vertical
+
+
+ True
+ False
+ UDP
+ 0
+
+
+ False
+ True
+ 0
+
+
+
+
+ True
+ False
+ <small>Use UDP communication when available</small>
+ True
+ 0
+
+
+
+ False
+ True
+ 1
+
+
+
+
+ True
+ True
+ 0
+
+
+
+
+ True
+ True
+ center
+
+
+ False
+ True
+ end
+ 1
+
+
+
+
+
+
+
+
+ True
+ True
+
+
+ True
+ False
+ 6
+ 6
+
+
+ True
+ False
+ center
+ vertical
+
+
+ True
+ False
+ IPv6
+ 0
+
+
+ False
+ True
+ 0
+
+
+
+
+ True
+ False
+ <small>Allow both IPv4 and IPv6 communication</small>
+ True
+ 0
+
+
+
+ False
+ True
+ 1
+
+
+
+
+ True
+ True
+ 0
+
+
+
+
+ True
+ True
+ center
+
+
+ False
+ True
+ end
+ 1
+
+
+
+
+
+
+
+
+ True
+ True
+
+
+ True
+ False
+ 6
+ 6
+
+
+ True
+ False
+ center
+ vertical
+
+
+ True
+ False
+ Local discovery
+ 0
+
+
+ False
+ True
+ 0
+
+
+
+
+ True
+ False
+ <small>Look for peers on the local network</small>
+ True
+ 0
+
+
+
+ False
+ True
+ 1
+
+
+
+
+ True
+ True
+ 0
+
+
+
+
+ True
+ True
+ center
+
+
+ False
+ True
+ end
+ 1
+
+
+
+
+
+
+
+
+ True
+ True
+
+
+ True
+ False
+ 6
+ 6
+
+
+ True
+ False
+ center
+ vertical
+
+
+ True
+ False
+ Hole punching
+ 0
+
+
+ False
+ True
+ 0
+
+
+
+
+ True
+ False
+ <small>Enable UDP <a href="https://en.wikipedia.org/wiki/Hole_punching_(networking)">hole punching</a></small>
+ True
+ 0
+
+
+
+ False
+ True
+ 1
+
+
+
+
+ True
+ True
+ 0
+
+
+
+
+ True
+ True
+ center
+
+
+ False
+ True
+ end
+ 1
+
+
+
+
+
+
+
+
+
+ False
+ True
+ 1
+
+
+
+
+ True
+ False
+ 6
+
+
+ True
+ True
+ True
+ Update bootstrap nodes
+ app.update-nodes
+
+
+ True
+ False
+ view-refresh-symbolic
+
+
+
+
+
+ False
+ True
+ end
+ 0
+
+
+
+
+ True
+ False
+ venom-symbolic
+
+
+ False
+ True
+ 1
+
+
+
+
+ True
+ False
+ <b>Bootstrap nodes</b>
+ True
+ 0
+
+
+ False
+ True
+ 2
+
+
+
+
+ False
+ True
+ 2
+
+
+
+
+ 450
+ 200
+ True
+ False
+ none
+
+
+
+ False
+ True
+ 3
+
+
+
+
+ True
+ True
+ 1
+
+
+
+
+ True
+ False
+ vertical
+
+
+
+
+
+
+
+
+
+
+
+ True
+ True
+ 2
+
+
+
+
+
+
+
+
+ page1
+ page1
+ 1
+
+
+
+
+ True
+ True
+ 6
+
+
+ True
+ False
+ none
+
+
+ True
+ False
+
+
+ True
+ False
+ vertical
+
+
+
+
+
+
+
+
+
+
+
+ True
+ True
+ 0
+
+
+
+
+ True
+ False
+ vertical
+ 6
+
+
+ True
+ False
+ 6
+
+
+ True
+ False
+ network-server-symbolic
+
+
+ False
+ True
+ 0
+
+
+
+
+ True
+ False
+ <b>Proxy</b>
+ True
+
+
+ False
+ True
+ 1
+
+
+
+
+ True
+ True
+ True
+
+
+ False
+ True
+ end
+ 2
+
+
+
+
+ False
+ True
+ 0
+
+
+
+
+ True
+ False
+ True
+
+
+ True
+ False
+ none
+
+
+ True
+ True
+
+
+ True
+ False
+ 6
+ vertical
+ 6
+
+
+ True
+ True
+ False
+ True
+ True
+
+
+ True
+ False
+ 6
+ vertical
+
+
+ True
+ False
+ System settings
+ 0
+
+
+ False
+ True
+ 0
+
+
+
+
+ True
+ False
+ <small>Use your systems proxy settings</small>
+ True
+ 0
+
+
+
+ False
+ True
+ 1
+
+
+
+
+
+
+ False
+ True
+ 1
+
+
+
+
+
+
+
+
+ True
+ True
+
+
+ True
+ False
+ 6
+ vertical
+ 6
+
+
+ True
+ True
+ False
+ True
+ proxy_system
+
+
+ True
+ False
+ 6
+ vertical
+
+
+ True
+ False
+ Manual settings
+ 0
+
+
+ False
+ True
+ 0
+
+
+
+
+ True
+ False
+ <small>Use custom proxy settings</small>
+ True
+ 0
+
+
+
+ False
+ True
+ 1
+
+
+
+
+
+
+ False
+ True
+ 0
+
+
+
+
+ True
+ False
+
+
+ True
+ False
+ vertical
+ 6
+
+
+ True
+ False
+ 6
+
+
+ True
+ True
+ Host
+ url
+
+
+ True
+ True
+ 0
+
+
+
+
+ True
+ True
+ 6
+ 6
+ number
+ port_adjustment
+ True
+ True
+ if-valid
+ 9150
+
+
+ False
+ True
+ end
+ 1
+
+
+
+
+ False
+ True
+ 0
+
+
+
+
+ True
+ False
+ <small>Set a SOCKS5 proxy to connect to</small>
+ True
+ 0
+
+
+
+ False
+ True
+ 1
+
+
+
+
+
+
+ False
+ True
+ 1
+
+
+
+
+
+
+
+
+
+
+
+ False
+ True
+ 1
+
+
+
+
+ True
+ True
+ 1
+
+
+
+
+ True
+ False
+ vertical
+
+
+
+
+
+
+
+
+
+
+
+ True
+ True
+ 2
+
+
+
+
+
+
+
+
+ page2
+ page2
+ 2
+
+
+
+
+ True
+ True
+ 2
+
+
+
+
+ True
+ True
+ 0
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/ui/settings_window.ui b/src/ui/settings_window.ui
deleted file mode 100644
index 710ef4b..0000000
--- a/src/ui/settings_window.ui
+++ /dev/null
@@ -1,386 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
- KiB/MiB
- False
-
-
- KB/MB
- True
-
-
-
-
- 365
- 1
- 10
-
-
- False
- Settings
- dialog
-
-
- False
- vertical
- 2
-
-
- False
- end
-
-
- gtk-close
- True
- True
- True
- True
- True
- True
-
-
- True
- True
- 0
-
-
-
-
- False
- True
- end
- 0
-
-
-
-
- True
- True
- 5
-
-
- True
- False
- 6
- vertical
-
-
- Keep history
- True
- True
- False
- 0
- top
- True
-
-
- False
- True
- 0
-
-
-
-
- True
- False
- 24
-
-
- True
- False
- vertical
-
-
- indefinitely
- True
- True
- False
- 0
- True
- True
- history_delete_radio
-
-
- False
- True
- 0
-
-
-
-
- True
- False
- 6
-
-
- delete after
- True
- True
- False
- 0
- True
- True
-
-
- False
- True
- 0
-
-
-
-
- True
- True
- history_delete_adjustment
- True
- if-valid
- 180
-
-
- False
- True
- 1
-
-
-
-
- True
- False
- days
-
-
- False
- True
- 2
-
-
-
-
- False
- True
- 1
-
-
-
-
-
-
- False
- True
- 1
-
-
-
-
- Show _others when I am typing
- True
- True
- False
- True
- 0
- True
-
-
- False
- True
- 2
-
-
-
-
- Show me when others are typing
- True
- True
- False
- 0
- True
-
-
- False
- True
- 3
-
-
-
-
-
-
- True
- False
- Privacy
-
-
- False
-
-
-
-
- True
- False
- 6
- vertical
- 6
-
-
- Flash window when a new message arrives
- True
- True
- False
- 0
- True
-
-
- False
- True
- 0
-
-
-
-
- Show notification when a new message arrives
- True
- True
- False
- 0
- True
-
-
- False
- True
- 1
-
-
-
-
- Minimize to system tray
- True
- True
- False
- 0
- True
-
-
- False
- True
- 2
-
-
-
-
- True
- False
- 6
-
-
- True
- False
- Show filesize in
-
-
- False
- True
- 0
-
-
-
-
- True
- False
- filesize_prefix_liststore
- 0
-
-
-
- 0
-
-
-
-
- False
- True
- 1
-
-
-
-
- False
- True
- 3
-
-
-
-
- True
- False
- 6
-
-
- True
- False
- Default Tox DNS ID suffix:
-
-
- False
- True
- 0
-
-
-
-
- True
- True
- True
-
-
- False
- True
- 1
-
-
-
-
- False
- True
- 2
-
-
-
-
- 1
-
-
-
-
- True
- False
- Miscellaneous
-
-
- 1
- False
-
-
-
-
- True
- True
- 1
-
-
-
-
-
- button1
-
-
-
diff --git a/src/ui/user_info_widget.ui b/src/ui/user_info_widget.ui
new file mode 100644
index 0000000..10315cc
--- /dev/null
+++ b/src/ui/user_info_widget.ui
@@ -0,0 +1,489 @@
+
+
+
+
+
+
+
+
+
+ False
+
+
+ True
+ False
+ 6
+ vertical
+ 12
+
+
+ True
+ False
+ 6
+ 6
+ 4
+ 5
+
+
+ False
+ True
+ 0
+
+
+
+
+ True
+ False
+ 6
+
+
+ True
+ True
+ True
+ Reset
+
+
+ True
+ False
+ edit-clear-all-symbolic
+
+
+
+
+
+ False
+ True
+ 0
+
+
+
+
+ True
+ False
+ True
+ True
+ Take a picture
+
+
+ True
+ False
+ camera-photo-symbolic
+
+
+
+
+
+ False
+ True
+ 1
+
+
+
+
+ True
+ True
+ Choose a file
+ Choose an avatar
+
+
+ False
+ False
+ end
+ 2
+
+
+
+
+ False
+ True
+ end
+ 1
+
+
+
+
+
+
+ True
+ False
+ 6
+
+
+ True
+ False
+ vertical
+
+
+
+
+
+
+
+
+
+
+
+ True
+ True
+ 0
+
+
+
+
+ True
+ False
+ vertical
+ 6
+
+
+ True
+ False
+ 6
+
+
+
+ False
+ True
+ 0
+
+
+
+
+ 400
+ True
+ False
+ none
+ False
+
+
+ True
+ True
+
+
+ True
+ False
+ 6
+ vertical
+ 6
+
+
+ True
+ False
+ Username:
+ 0
+
+
+
+
+
+ False
+ True
+ 0
+
+
+
+
+ True
+ True
+ True
+ ●
+ name
+
+
+ False
+ True
+ 1
+
+
+
+
+
+
+
+
+ True
+ True
+
+
+ True
+ False
+ 6
+ vertical
+ 6
+
+
+ True
+ False
+ Status message:
+ True
+ 0
+
+
+
+
+
+ False
+ True
+ 0
+
+
+
+
+ True
+ True
+ True
+ face-smile-symbolic
+ Insert Emoji
+ Insert Emoji
+ True
+
+
+ False
+ True
+ 1
+
+
+
+
+
+
+
+
+
+ True
+ True
+ 1
+
+
+
+
+ False
+ True
+ 0
+
+
+
+
+ True
+ False
+ vertical
+ 6
+
+
+ True
+ False
+ Tox
+ 0
+
+
+
+
+
+ False
+ True
+ 0
+
+
+
+
+ True
+ False
+ none
+ False
+
+
+ True
+ True
+
+
+ True
+ False
+ 6
+ vertical
+ 6
+
+
+ True
+ False
+ ID:
+ True
+ label_id
+ 0
+
+
+
+
+
+ False
+ True
+ 0
+
+
+
+
+ True
+ False
+ 6
+
+
+ True
+ False
+ ###########################
+ True
+ end
+ 0
+
+
+
+ False
+ True
+ 0
+
+
+
+
+ True
+ True
+ True
+ Copy to clipboard
+ win.copy_id
+ True
+
+
+ True
+ False
+ edit-copy-symbolic
+
+
+
+
+
+ False
+ True
+ end
+ 1
+
+
+
+
+ False
+ True
+ end
+ 1
+
+
+
+
+
+
+
+
+
+ False
+ True
+ 1
+
+
+
+
+ False
+ True
+ 1
+
+
+
+
+ Apply
+ True
+ True
+ True
+
+
+
+ False
+ True
+ 2
+
+
+
+
+ True
+ True
+ 1
+
+
+
+
+ True
+ False
+ vertical
+
+
+
+
+
+
+
+
+
+
+
+ True
+ True
+ 2
+
+
+
+
diff --git a/src/ui/user_info_window.ui b/src/ui/user_info_window.ui
deleted file mode 100644
index 2682aaf..0000000
--- a/src/ui/user_info_window.ui
+++ /dev/null
@@ -1,299 +0,0 @@
-
-
-
-
-
- True
- False
- 5
- 5
- 5
- vertical
- 6
-
-
- True
- False
- 0
- none
-
-
- True
- False
- 12
-
-
- True
- False
- vertical
- 12
-
-
- True
- False
- 12
-
-
- True
- False
- 0
- ID:
- True
- label_id
-
-
- False
- True
- 0
-
-
-
-
- True
- False
- 6
-
-
- True
- False
- 0
- #ID#
- True
- end
-
-
- False
- True
- 0
-
-
-
-
- False
- True
- True
- True
- image1
-
-
- False
- True
- 1
-
-
-
-
- False
- True
- 1
-
-
-
-
- False
- True
- 0
-
-
-
-
- False
- True
- gtk-missing-image
- 0
-
-
- True
- True
- 1
-
-
-
-
-
-
-
-
- True
- False
- <b>Tox</b>
- True
-
-
-
-
- False
- True
- 0
-
-
-
-
- True
- False
- 0
- none
-
-
- True
- False
- 12
-
-
- True
- False
- 6
- 12
-
-
- True
- True
- True
- ●
- True
-
-
- 1
- 0
-
-
-
-
- True
- True
- True
- ●
- True
-
-
- 1
- 1
-
-
-
-
- True
- False
- 0
- Status message:
- True
- entry_statusmessage
-
-
- 0
- 1
-
-
-
-
- True
- False
- 0
- Name:
-
-
- 0
- 0
-
-
-
-
- False
- True
- 6
-
-
- 44
- 41
- True
- False
- gtk-missing-image
-
-
- False
- True
- 0
-
-
-
-
- True
- False
- Icon:
-
-
- False
- True
- 1
-
-
-
-
- 0
- 2
-
-
-
-
- False
- True
- 6
-
-
- True
- True
-
-
- True
- True
- 0
-
-
-
-
- _Browse...
- False
- True
- True
- True
- center
- True
-
-
- False
- True
- 1
-
-
-
-
- 1
- 2
-
-
-
-
-
-
-
-
- True
- False
- <b>User</b>
- True
-
-
-
-
- False
- True
- 1
-
-
-
-
- True
- False
- gtk-copy
-
-
diff --git a/src/ui/user_status_menu.ui b/src/ui/user_status_menu.ui
new file mode 100644
index 0000000..8d930dc
--- /dev/null
+++ b/src/ui/user_status_menu.ui
@@ -0,0 +1,47 @@
+
+
+
+
+
+
+
+
+
diff --git a/src/ui/venom.gresource.xml b/src/ui/venom.gresource.xml
index 4d414a1..598986e 100644
--- a/src/ui/venom.gresource.xml
+++ b/src/ui/venom.gresource.xml
@@ -1,11 +1,50 @@
+
-
- add_contact_dialog.ui
- contact_list.ui
- conversation_window.ui
- chat_filetransfer.ui
- user_info_window.ui
- settings_window.ui
+
+ add_contact_widget.ui
+ app_menu.ui
+ application_window.ui
+ conference_info_widget.ui
+ conference_invite_entry.ui
+ conference_window.ui
+ contact_list_entry.ui
+ contact_list_request_entry.ui
+ contact_list_widget.ui
+ conversation_window.ui
+ create_groupchat_widget.ui
+ file_transfer_entry.ui
+ file_transfer_entry_inline.ui
+ file_transfer_widget.ui
+ friend_info_widget.ui
+ friend_request_widget.ui
+ message_widget.ui
+ node_widget.ui
+ peer_entry.ui
+ peer_entry_compact.ui
+ settings_widget.ui
+ user_info_widget.ui
+ user_status_menu.ui
+ welcome_widget.ui
+
+
+ custom.css
diff --git a/src/ui/welcome_widget.ui b/src/ui/welcome_widget.ui
new file mode 100644
index 0000000..3a2ff90
--- /dev/null
+++ b/src/ui/welcome_widget.ui
@@ -0,0 +1,206 @@
+
+
+
+
+
+
+
+
+ True
+ False
+ center
+ center
+ 12
+ vertical
+ 12
+
+
+ True
+ False
+ vertical
+
+
+ True
+ False
+ 144
+ venom-symbolic
+ 6
+
+
+
+ False
+ True
+ 0
+
+
+
+
+ True
+ False
+ <big>A new kind of instant messaging</big>
+ True
+
+
+
+ False
+ True
+ 1
+
+
+
+
+ True
+ False
+ Chat with your friends and family without anyone else listening in.
+ center
+ True
+
+
+
+ False
+ True
+ 2
+
+
+
+
+ False
+ True
+ 1
+
+
+
+
+ True
+ False
+ center
+ 6
+
+
+ True
+ True
+ True
+ center
+
+
+ True
+ False
+ 6
+
+
+ True
+ False
+ dialog-information-symbolic
+
+
+ False
+ True
+ 0
+
+
+
+
+ True
+ False
+ Learn more
+
+
+ False
+ True
+ 1
+
+
+
+
+
+
+
+ False
+ True
+ 0
+
+
+
+
+ True
+ True
+ True
+ center
+
+
+ True
+ False
+ 6
+
+
+ True
+ False
+ help-about-symbolic
+
+
+ False
+ True
+ 0
+
+
+
+
+ True
+ False
+ Get involved
+
+
+ False
+ True
+ 1
+
+
+
+
+
+
+
+ False
+ True
+ 1
+
+
+
+
+ False
+ True
+ 2
+
+
+
+
diff --git a/src/undo/SimpleUndoStack.vala b/src/undo/SimpleUndoStack.vala
new file mode 100644
index 0000000..479bb9a
--- /dev/null
+++ b/src/undo/SimpleUndoStack.vala
@@ -0,0 +1,116 @@
+/*
+ * SimpleUndoStack.vala
+ *
+ * Copyright (C) 2018 Venom authors and contributors
+ *
+ * This file is part of Venom.
+ *
+ * Venom is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Venom is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Venom. If not, see .
+ */
+
+namespace Undo {
+ public class SimpleUndoStack : UndoStack, GLib.Object {
+ public bool is_busy { get; protected set; }
+
+ private Gee.Deque undo_stack;
+ private Gee.Deque redo_stack;
+ private GLib.SimpleAction undo_action;
+ private GLib.SimpleAction redo_action;
+
+ public SimpleUndoStack() {
+ undo_stack = new Gee.LinkedList();
+ redo_stack = new Gee.LinkedList();
+ }
+
+ public virtual void clear() {
+ if (undo_action != null && !undo_stack.is_empty) {
+ undo_action.set_enabled(false);
+ }
+ if (redo_action != null && !redo_stack.is_empty) {
+ redo_action.set_enabled(false);
+ }
+ undo_stack.clear();
+ redo_stack.clear();
+ }
+
+ public virtual void offer(UndoCommand command) {
+ is_busy = true;
+ if (command.run_on_init()) {
+ command.redo();
+ }
+
+ if (undo_action != null && undo_stack.is_empty) {
+ undo_action.set_enabled(true);
+ }
+
+ if (!redo_stack.is_empty || undo_stack.is_empty || !undo_stack.peek_tail().try_merge(command)) {
+ undo_stack.offer_tail(command);
+ }
+
+ if (redo_action != null && !redo_stack.is_empty) {
+ redo_action.set_enabled(false);
+ }
+ redo_stack.clear();
+ is_busy = false;
+ }
+
+ private void undo() {
+ is_busy = true;
+ var command = undo_stack.poll_tail();
+ if (undo_action != null && undo_stack.is_empty) {
+ undo_action.set_enabled(false);
+ }
+
+ command.undo();
+ if (redo_action != null && redo_stack.is_empty) {
+ redo_action.set_enabled(true);
+ }
+ redo_stack.offer_tail(command);
+ is_busy = false;
+ }
+
+ private void redo() {
+ is_busy = true;
+ var command = redo_stack.poll_tail();
+ if (redo_action != null && redo_stack.is_empty) {
+ redo_action.set_enabled(false);
+ }
+
+ command.redo();
+ if (undo_action != null && undo_stack.is_empty) {
+ undo_action.set_enabled(true);
+ }
+ undo_stack.offer_tail(command);
+ is_busy = false;
+ }
+
+ public virtual GLib.Action create_undo_action(string name) {
+ if (undo_action == null) {
+ undo_action = new GLib.SimpleAction(name, null);
+ undo_action.activate.connect(undo);
+ undo_action.set_enabled(!undo_stack.is_empty);
+ }
+ return undo_action;
+ }
+
+ public virtual GLib.Action create_redo_action(string name) {
+ if (redo_action == null) {
+ redo_action = new GLib.SimpleAction(name, null);
+ redo_action.activate.connect(redo);
+ redo_action.set_enabled(!redo_stack.is_empty);
+ }
+ return redo_action;
+ }
+ }
+}
diff --git a/src/undo/TextBufferUndoBinding.vala b/src/undo/TextBufferUndoBinding.vala
new file mode 100644
index 0000000..437fafd
--- /dev/null
+++ b/src/undo/TextBufferUndoBinding.vala
@@ -0,0 +1,193 @@
+/*
+ * TextBufferEditCommand.vala
+ *
+ * Copyright (C) 2018 Venom authors and contributors
+ *
+ * This file is part of Venom.
+ *
+ * Venom is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Venom is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Venom. If not, see .
+ */
+
+namespace Undo {
+ public abstract class TextBufferEditCommand : UndoCommand, GLib.Object {
+ protected unowned Gtk.TextBuffer buffer;
+ protected string text;
+ protected int start;
+ protected int end;
+
+ public abstract void redo();
+ public abstract void undo();
+ public abstract bool try_merge(UndoCommand command);
+
+ public virtual bool run_on_init() {
+ return false;
+ }
+
+ protected void place_cursor(int position) {
+ Gtk.TextIter iter;
+ buffer.get_iter_at_offset(out iter, position);
+ buffer.place_cursor(iter);
+ }
+
+ protected void insert_section() {
+ Gtk.TextIter iter_start;
+ buffer.get_iter_at_offset(out iter_start, start);
+ buffer.begin_user_action();
+ buffer.insert(ref iter_start, text, -1);
+ buffer.end_user_action();
+ }
+
+ protected void delete_section() {
+ Gtk.TextIter iter_start;
+ Gtk.TextIter iter_end;
+
+ buffer.get_iter_at_offset(out iter_start, start);
+ buffer.get_iter_at_offset(out iter_end, end);
+ buffer.begin_user_action();
+ buffer.delete (ref iter_start, ref iter_end);
+ buffer.end_user_action();
+ }
+ }
+
+ public class DeleteRangeCommand : TextBufferEditCommand {
+ public DeleteRangeCommand(Gtk.TextBuffer buffer, ref Gtk.TextIter start, ref Gtk.TextIter end) {
+ this.buffer = buffer;
+ this.text = buffer.get_slice(start, end, true);
+ this.start = start.get_offset();
+ this.end = end.get_offset();
+ }
+
+ public override bool try_merge(UndoCommand command) {
+ if (command is DeleteRangeCommand) {
+ var c = command as DeleteRangeCommand;
+ if (c.buffer == buffer && (c.end - c.start == 1)) {
+ if (c.end == start) {
+ text = c.text + text;
+ start = c.start;
+ end = start + text.char_count();
+ return true;
+ } else if (end == c.start) {
+ text += c.text;
+ end = start + text.char_count();
+ return true;
+ }
+ }
+ }
+ return false;
+ }
+
+ public override void redo() {
+ delete_section();
+ place_cursor(start);
+ }
+
+ public override void undo() {
+ insert_section();
+ place_cursor(end);
+ }
+ }
+
+ public class InsertTextCommand : TextBufferEditCommand {
+ public InsertTextCommand(Gtk.TextBuffer buffer, ref Gtk.TextIter pos, string text, int length) {
+ this.buffer = buffer;
+ this.text = text.substring(0, length);
+ this.start = pos.get_offset();
+ this.end = start + this.text.char_count();
+ }
+
+ public override bool try_merge(UndoCommand command) {
+ if (command is InsertTextCommand) {
+ var c = command as InsertTextCommand;
+ if (c.buffer == buffer && (c.end - c.start == 1)) {
+ if (c.start == start) {
+ text = c.text + text;
+ end = start + text.char_count();
+ return true;
+ } else if (c.start == end && !c.text.get_char().isspace()) {
+ text += c.text;
+ end = start + text.char_count();
+ return true;
+ }
+ }
+ }
+ return false;
+ }
+
+ public override void redo() {
+ insert_section();
+ place_cursor(end);
+ }
+
+ public override void undo() {
+ delete_section();
+ place_cursor(start);
+ }
+ }
+
+ public class TextBufferUndoBinding : GLib.Object {
+ public Gtk.TextBuffer buffer { get; set; }
+ public UndoStack undo_stack { get; set; }
+ public GLib.Action undo_action { get; set; }
+ public GLib.Action redo_action { get; set; }
+
+ public TextBufferUndoBinding() {
+ this.undo_stack = new SimpleUndoStack();
+ this.undo_action = undo_stack.create_undo_action("undo");
+ this.redo_action = undo_stack.create_redo_action("redo");
+ }
+
+ public void add_actions_to(GLib.ActionMap action_map) {
+ action_map.add_action(undo_action);
+ action_map.add_action(redo_action);
+ }
+
+ public void bind_buffer(Gtk.TextBuffer buffer) {
+ this.buffer = buffer;
+ buffer.insert_text.connect(on_buffer_insert_text);
+ buffer.delete_range.connect(on_buffer_delete_range);
+ }
+
+ public void clear() {
+ undo_stack.clear();
+ }
+
+ public void populate_popup(Gtk.Menu menu) {
+ var separator = new Gtk.SeparatorMenuItem();
+ separator.show();
+ menu.prepend(separator);
+ var redo = new Gtk.MenuItem.with_mnemonic(_("_Redo"));
+ redo_action.bind_property("enabled", redo, "sensitive", BindingFlags.SYNC_CREATE);
+ redo.activate.connect(() => { redo_action.activate(null); });
+ redo.show();
+ menu.prepend(redo);
+ var undo = new Gtk.MenuItem.with_mnemonic(_("_Undo"));
+ undo_action.bind_property("enabled", undo, "sensitive", BindingFlags.SYNC_CREATE);
+ undo.activate.connect(() => { undo_action.activate(null); });
+ undo.show();
+ menu.prepend(undo);
+ }
+
+ private void on_buffer_insert_text(ref Gtk.TextIter pos, string text, int len) {
+ if (!undo_stack.is_busy) {
+ undo_stack.offer(new InsertTextCommand(buffer, ref pos, text, len));
+ }
+ }
+
+ private void on_buffer_delete_range(ref Gtk.TextIter start, ref Gtk.TextIter end) {
+ if (!undo_stack.is_busy) {
+ undo_stack.offer(new DeleteRangeCommand(buffer, ref start, ref end));
+ }
+ }
+ }
+}
diff --git a/src/ui/SearchEntry.vala b/src/undo/UndoCommand.vala
similarity index 69%
rename from src/ui/SearchEntry.vala
rename to src/undo/UndoCommand.vala
index 57aa459..f8d2532 100644
--- a/src/ui/SearchEntry.vala
+++ b/src/undo/UndoCommand.vala
@@ -1,7 +1,7 @@
/*
- * SearchEntry.vala
+ * UndoCommand.vala
*
- * Copyright (C) 2013-2014 Venom authors and contributors
+ * Copyright (C) 2018 Venom authors and contributors
*
* This file is part of Venom.
*
@@ -19,11 +19,11 @@
* along with Venom. If not, see .
*/
-namespace Venom {
- public class SearchEntry : Gtk.Entry {
- public SearchEntry() {
- primary_icon_name = "edit-find-symbolic";
- margin = 6;
- }
+namespace Undo {
+ public interface UndoCommand : GLib.Object {
+ public abstract void redo();
+ public abstract void undo();
+ public abstract bool run_on_init();
+ public abstract bool try_merge(UndoCommand command);
}
}
diff --git a/src/config.h.in b/src/undo/UndoStack.vala
similarity index 55%
rename from src/config.h.in
rename to src/undo/UndoStack.vala
index 1ee3d3e..f00d40d 100644
--- a/src/config.h.in
+++ b/src/undo/UndoStack.vala
@@ -1,7 +1,7 @@
/*
- * config.h.in
+ * UndoStack.vala
*
- * Copyright (C) 2013-2014 Venom authors and contributors
+ * Copyright (C) 2018 Venom authors and contributors
*
* This file is part of Venom.
*
@@ -19,18 +19,12 @@
* along with Venom. If not, see .
*/
-#ifndef CONFIG_H
-#define CONFIG_H
-
-#define VENOM_VERSION_MAJOR @VENOM_VERSION_MAJOR@
-#define VENOM_VERSION_MINOR @VENOM_VERSION_MINOR@
-#define VENOM_VERSION_PATCH @VENOM_VERSION_PATCH@
-#define VENOM_VERSION "@VENOM_VERSION@"
-
-#define VENOM_COPYRIGHT_NOTICE "@VENOM_COPYRIGHT_NOTICE@"
-#define VENOM_SHORT_DESCRIPTION "@VENOM_SHORT_DESCRIPTION@"
-#define VENOM_WEBSITE "@VENOM_WEBSITE@"
-
-#define VENOM_GETTEXT_PACKAGE "@GETTEXT_PACKAGE@"
-#define VENOM_GETTEXT_PATH "@GETTEXT_PATH@"
-#endif
+namespace Undo {
+ public interface UndoStack : GLib.Object {
+ public abstract bool is_busy { get; protected set; }
+ public abstract void offer(UndoCommand command);
+ public abstract void clear();
+ public abstract GLib.Action create_undo_action(string name);
+ public abstract GLib.Action create_redo_action(string name);
+ }
+}
diff --git a/src/vapi/config.vapi b/src/vapi/config.vapi
index a631160..8e4ad06 100644
--- a/src/vapi/config.vapi
+++ b/src/vapi/config.vapi
@@ -1,7 +1,7 @@
/*
* config.vapi
*
- * Copyright (C) 2013-2014 Venom authors and contributors
+ * Copyright (C) 2013-2018 Venom authors and contributors
*
* This file is part of Venom.
*
@@ -19,17 +19,11 @@
* along with Venom. If not, see .
*/
-[CCode (cprefix = "", lower_case_cprefix = "VENOM_", cheader_filename = "config.h")]
-namespace Venom.Config {
- public const int VERSION_MAJOR;
- public const int VERSION_MINOR;
- public const int VERSION_PATCH;
+[CCode (cheader_filename = "config.h", cprefix = "", lower_case_cprefix = "")]
+namespace Config {
+ [CCode(cname="VENOM_VERSION")]
public const string VERSION;
- public const string COPYRIGHT_NOTICE;
- public const string SHORT_DESCRIPTION;
- public const string WEBSITE;
-
public const string GETTEXT_PACKAGE;
public const string GETTEXT_PATH;
}
diff --git a/src/vapi/gtk+-3.0.deps b/src/vapi/gtk+-3.0.deps
deleted file mode 100644
index 822b12b..0000000
--- a/src/vapi/gtk+-3.0.deps
+++ /dev/null
@@ -1,7 +0,0 @@
-gio-2.0
-atk
-cairo
-gdk-pixbuf-2.0
-gdk-3.0
-pango
-x11
diff --git a/src/vapi/gtk+-3.0.vapi b/src/vapi/gtk+-3.0.vapi
deleted file mode 100644
index 4a20e9f..0000000
--- a/src/vapi/gtk+-3.0.vapi
+++ /dev/null
@@ -1,9695 +0,0 @@
-/* gtk+-3.0.vapi generated by vapigen, do not modify. */
-
-[CCode (cprefix = "Gtk", gir_namespace = "Gtk", gir_version = "3.0", lower_case_cprefix = "gtk_")]
-namespace Gtk {
- [Deprecated (since = "3.10")]
- namespace Stock {
- [CCode (cheader_filename = "gtk/gtk.h")]
- public const string ABOUT;
- [CCode (cheader_filename = "gtk/gtk.h")]
- public const string ADD;
- [CCode (cheader_filename = "gtk/gtk.h")]
- public const string APPLY;
- [CCode (cheader_filename = "gtk/gtk.h")]
- public const string BOLD;
- [CCode (cheader_filename = "gtk/gtk.h")]
- public const string CANCEL;
- [CCode (cheader_filename = "gtk/gtk.h")]
- public const string CAPS_LOCK_WARNING;
- [CCode (cheader_filename = "gtk/gtk.h")]
- public const string CDROM;
- [CCode (cheader_filename = "gtk/gtk.h")]
- public const string CLEAR;
- [CCode (cheader_filename = "gtk/gtk.h")]
- public const string CLOSE;
- [CCode (cheader_filename = "gtk/gtk.h")]
- public const string COLOR_PICKER;
- [CCode (cheader_filename = "gtk/gtk.h")]
- public const string CONNECT;
- [CCode (cheader_filename = "gtk/gtk.h")]
- public const string CONVERT;
- [CCode (cheader_filename = "gtk/gtk.h")]
- public const string COPY;
- [CCode (cheader_filename = "gtk/gtk.h")]
- public const string CUT;
- [CCode (cheader_filename = "gtk/gtk.h")]
- public const string DELETE;
- [CCode (cheader_filename = "gtk/gtk.h")]
- public const string DIALOG_AUTHENTICATION;
- [CCode (cheader_filename = "gtk/gtk.h")]
- public const string DIALOG_ERROR;
- [CCode (cheader_filename = "gtk/gtk.h")]
- public const string DIALOG_INFO;
- [CCode (cheader_filename = "gtk/gtk.h")]
- public const string DIALOG_QUESTION;
- [CCode (cheader_filename = "gtk/gtk.h")]
- public const string DIALOG_WARNING;
- [CCode (cheader_filename = "gtk/gtk.h")]
- public const string DIRECTORY;
- [CCode (cheader_filename = "gtk/gtk.h")]
- public const string DISCARD;
- [CCode (cheader_filename = "gtk/gtk.h")]
- public const string DISCONNECT;
- [CCode (cheader_filename = "gtk/gtk.h")]
- public const string DND;
- [CCode (cheader_filename = "gtk/gtk.h")]
- public const string DND_MULTIPLE;
- [CCode (cheader_filename = "gtk/gtk.h")]
- public const string EDIT;
- [CCode (cheader_filename = "gtk/gtk.h")]
- public const string EXECUTE;
- [CCode (cheader_filename = "gtk/gtk.h")]
- public const string FILE;
- [CCode (cheader_filename = "gtk/gtk.h")]
- public const string FIND;
- [CCode (cheader_filename = "gtk/gtk.h")]
- public const string FIND_AND_REPLACE;
- [CCode (cheader_filename = "gtk/gtk.h")]
- public const string FLOPPY;
- [CCode (cheader_filename = "gtk/gtk.h")]
- public const string FULLSCREEN;
- [CCode (cheader_filename = "gtk/gtk.h")]
- public const string GOTO_BOTTOM;
- [CCode (cheader_filename = "gtk/gtk.h")]
- public const string GOTO_FIRST;
- [CCode (cheader_filename = "gtk/gtk.h")]
- public const string GOTO_LAST;
- [CCode (cheader_filename = "gtk/gtk.h")]
- public const string GOTO_TOP;
- [CCode (cheader_filename = "gtk/gtk.h")]
- public const string GO_BACK;
- [CCode (cheader_filename = "gtk/gtk.h")]
- public const string GO_DOWN;
- [CCode (cheader_filename = "gtk/gtk.h")]
- public const string GO_FORWARD;
- [CCode (cheader_filename = "gtk/gtk.h")]
- public const string GO_UP;
- [CCode (cheader_filename = "gtk/gtk.h")]
- public const string HARDDISK;
- [CCode (cheader_filename = "gtk/gtk.h")]
- public const string HELP;
- [CCode (cheader_filename = "gtk/gtk.h")]
- public const string HOME;
- [CCode (cheader_filename = "gtk/gtk.h")]
- public const string INDENT;
- [CCode (cheader_filename = "gtk/gtk.h")]
- public const string INDEX;
- [CCode (cheader_filename = "gtk/gtk.h")]
- public const string INFO;
- [CCode (cheader_filename = "gtk/gtk.h")]
- public const string ITALIC;
- [CCode (cheader_filename = "gtk/gtk.h")]
- public const string JUMP_TO;
- [CCode (cheader_filename = "gtk/gtk.h")]
- public const string JUSTIFY_CENTER;
- [CCode (cheader_filename = "gtk/gtk.h")]
- public const string JUSTIFY_FILL;
- [CCode (cheader_filename = "gtk/gtk.h")]
- public const string JUSTIFY_LEFT;
- [CCode (cheader_filename = "gtk/gtk.h")]
- public const string JUSTIFY_RIGHT;
- [CCode (cheader_filename = "gtk/gtk.h")]
- public const string LEAVE_FULLSCREEN;
- [CCode (cheader_filename = "gtk/gtk.h")]
- public const string MEDIA_FORWARD;
- [CCode (cheader_filename = "gtk/gtk.h")]
- public const string MEDIA_NEXT;
- [CCode (cheader_filename = "gtk/gtk.h")]
- public const string MEDIA_PAUSE;
- [CCode (cheader_filename = "gtk/gtk.h")]
- public const string MEDIA_PLAY;
- [CCode (cheader_filename = "gtk/gtk.h")]
- public const string MEDIA_PREVIOUS;
- [CCode (cheader_filename = "gtk/gtk.h")]
- public const string MEDIA_RECORD;
- [CCode (cheader_filename = "gtk/gtk.h")]
- public const string MEDIA_REWIND;
- [CCode (cheader_filename = "gtk/gtk.h")]
- public const string MEDIA_STOP;
- [CCode (cheader_filename = "gtk/gtk.h")]
- public const string MISSING_IMAGE;
- [CCode (cheader_filename = "gtk/gtk.h")]
- public const string NETWORK;
- [CCode (cheader_filename = "gtk/gtk.h")]
- public const string NEW;
- [CCode (cheader_filename = "gtk/gtk.h")]
- public const string NO;
- [CCode (cheader_filename = "gtk/gtk.h")]
- public const string OK;
- [CCode (cheader_filename = "gtk/gtk.h")]
- public const string OPEN;
- [CCode (cheader_filename = "gtk/gtk.h")]
- public const string ORIENTATION_LANDSCAPE;
- [CCode (cheader_filename = "gtk/gtk.h")]
- public const string ORIENTATION_PORTRAIT;
- [CCode (cheader_filename = "gtk/gtk.h")]
- public const string ORIENTATION_REVERSE_LANDSCAPE;
- [CCode (cheader_filename = "gtk/gtk.h")]
- public const string ORIENTATION_REVERSE_PORTRAIT;
- [CCode (cheader_filename = "gtk/gtk.h")]
- public const string PAGE_SETUP;
- [CCode (cheader_filename = "gtk/gtk.h")]
- public const string PASTE;
- [CCode (cheader_filename = "gtk/gtk.h")]
- public const string PREFERENCES;
- [CCode (cheader_filename = "gtk/gtk.h")]
- public const string PRINT;
- [CCode (cheader_filename = "gtk/gtk.h")]
- public const string PRINT_ERROR;
- [CCode (cheader_filename = "gtk/gtk.h")]
- public const string PRINT_PAUSED;
- [CCode (cheader_filename = "gtk/gtk.h")]
- public const string PRINT_PREVIEW;
- [CCode (cheader_filename = "gtk/gtk.h")]
- public const string PRINT_REPORT;
- [CCode (cheader_filename = "gtk/gtk.h")]
- public const string PRINT_WARNING;
- [CCode (cheader_filename = "gtk/gtk.h")]
- public const string PROPERTIES;
- [CCode (cheader_filename = "gtk/gtk.h")]
- public const string QUIT;
- [CCode (cheader_filename = "gtk/gtk.h")]
- public const string REDO;
- [CCode (cheader_filename = "gtk/gtk.h")]
- public const string REFRESH;
- [CCode (cheader_filename = "gtk/gtk.h")]
- public const string REMOVE;
- [CCode (cheader_filename = "gtk/gtk.h")]
- public const string REVERT_TO_SAVED;
- [CCode (cheader_filename = "gtk/gtk.h")]
- public const string SAVE;
- [CCode (cheader_filename = "gtk/gtk.h")]
- public const string SAVE_AS;
- [CCode (cheader_filename = "gtk/gtk.h")]
- public const string SELECT_ALL;
- [CCode (cheader_filename = "gtk/gtk.h")]
- public const string SELECT_COLOR;
- [CCode (cheader_filename = "gtk/gtk.h")]
- public const string SELECT_FONT;
- [CCode (cheader_filename = "gtk/gtk.h")]
- public const string SORT_ASCENDING;
- [CCode (cheader_filename = "gtk/gtk.h")]
- public const string SORT_DESCENDING;
- [CCode (cheader_filename = "gtk/gtk.h")]
- public const string SPELL_CHECK;
- [CCode (cheader_filename = "gtk/gtk.h")]
- public const string STOP;
- [CCode (cheader_filename = "gtk/gtk.h")]
- public const string STRIKETHROUGH;
- [CCode (cheader_filename = "gtk/gtk.h")]
- public const string UNDELETE;
- [CCode (cheader_filename = "gtk/gtk.h")]
- public const string UNDERLINE;
- [CCode (cheader_filename = "gtk/gtk.h")]
- public const string UNDO;
- [CCode (cheader_filename = "gtk/gtk.h")]
- public const string UNINDENT;
- [CCode (cheader_filename = "gtk/gtk.h")]
- public const string YES;
- [CCode (cheader_filename = "gtk/gtk.h")]
- public const string ZOOM_100;
- [CCode (cheader_filename = "gtk/gtk.h")]
- public const string ZOOM_FIT;
- [CCode (cheader_filename = "gtk/gtk.h")]
- public const string ZOOM_IN;
- [CCode (cheader_filename = "gtk/gtk.h")]
- public const string ZOOM_OUT;
- [CCode (cheader_filename = "gtk/gtk.h")]
- public static void add (Gtk.StockItem[] items);
- [CCode (cheader_filename = "gtk/gtk.h")]
- public static void add_static (Gtk.StockItem[] items);
- [CCode (cheader_filename = "gtk/gtk.h")]
- public static GLib.SList list_ids ();
- [CCode (cheader_filename = "gtk/gtk.h")]
- public static bool lookup (string stock_id, out Gtk.StockItem item);
- [CCode (cheader_filename = "gtk/gtk.h")]
- public static void set_translate_func (string domain, owned Gtk.TranslateFunc func);
- }
- [CCode (cheader_filename = "gtk/gtk.h", type_id = "gtk_about_dialog_get_type ()")]
- public class AboutDialog : Gtk.Dialog, Atk.Implementor, Gtk.Buildable {
- [CCode (has_construct_function = false, type = "GtkWidget*")]
- public AboutDialog ();
- public void add_credit_section (string section_name, [CCode (array_length = false, array_null_terminated = true)] string[] people);
- [CCode (array_length = false, array_null_terminated = true)]
- public unowned string[] get_artists ();
- [CCode (array_length = false, array_null_terminated = true)]
- public unowned string[] get_authors ();
- public unowned string get_comments ();
- public unowned string get_copyright ();
- [CCode (array_length = false, array_null_terminated = true)]
- public unowned string[] get_documenters ();
- public unowned string get_license ();
- public Gtk.License get_license_type ();
- public unowned Gdk.Pixbuf get_logo ();
- public unowned string get_logo_icon_name ();
- public unowned string get_program_name ();
- public unowned string get_translator_credits ();
- public unowned string get_version ();
- public unowned string get_website ();
- public unowned string get_website_label ();
- public bool get_wrap_license ();
- public void set_artists ([CCode (array_length = false, array_null_terminated = true)] string[] artists);
- public void set_authors ([CCode (array_length = false, array_null_terminated = true)] string[] authors);
- public void set_comments (string comments);
- public void set_copyright (string copyright);
- public void set_documenters ([CCode (array_length = false, array_null_terminated = true)] string[] documenters);
- public void set_license (string license);
- public void set_license_type (Gtk.License license_type);
- public void set_logo (Gdk.Pixbuf logo);
- public void set_logo_icon_name (string icon_name);
- public void set_program_name (string name);
- public void set_translator_credits (string translator_credits);
- public void set_version (string version);
- public void set_website (string website);
- public void set_website_label (string website_label);
- public void set_wrap_license (bool wrap_license);
- [CCode (array_length = false, array_null_terminated = true)]
- public string[] artists { get; set; }
- [CCode (array_length = false, array_null_terminated = true)]
- public string[] authors { get; set; }
- public string comments { get; set; }
- public string copyright { get; set; }
- [CCode (array_length = false, array_null_terminated = true)]
- public string[] documenters { get; set; }
- public string license { get; set; }
- public Gtk.License license_type { get; set; }
- public Gdk.Pixbuf logo { get; set; }
- public string logo_icon_name { get; set; }
- public string program_name { get; set; }
- public string translator_credits { get; set; }
- public string version { get; set; }
- public string website { get; set; }
- public string website_label { get; set; }
- public bool wrap_license { get; set; }
- public virtual signal bool activate_link (string uri);
- }
- [CCode (cheader_filename = "gtk/gtk.h", type_id = "gtk_accel_group_get_type ()")]
- public class AccelGroup : GLib.Object {
- [CCode (has_construct_function = false)]
- public AccelGroup ();
- public bool activate (GLib.Quark accel_quark, GLib.Object acceleratable, uint accel_key, Gdk.ModifierType accel_mods);
- public void connect (uint accel_key, Gdk.ModifierType accel_mods, Gtk.AccelFlags accel_flags, [CCode (type = "GClosure*")] owned Gtk.AccelGroupActivate closure);
- public void connect_by_path (string accel_path, [CCode (type = "GClosure*")] owned Gtk.AccelGroupActivate closure);
- public bool disconnect (GLib.Closure closure);
- public bool disconnect_key (uint accel_key, Gdk.ModifierType accel_mods);
- public Gtk.AccelKey* find (Gtk.AccelGroupFindFunc find_func);
- public static unowned Gtk.AccelGroup from_accel_closure (GLib.Closure closure);
- public bool get_is_locked ();
- public Gdk.ModifierType get_modifier_mask ();
- public void @lock ();
- [CCode (array_length_type = "guint")]
- public unowned Gtk.AccelGroupEntry[] query (uint accel_key, Gdk.ModifierType accel_mods);
- public void unlock ();
- public bool is_locked { get; }
- public Gdk.ModifierType modifier_mask { get; }
- public virtual signal bool accel_activate (GLib.Object p0, uint p1, Gdk.ModifierType p2);
- public virtual signal void accel_changed (uint keyval, Gdk.ModifierType modifier, GLib.Closure accel_closure);
- }
- [CCode (cheader_filename = "gtk/gtk.h", type_id = "gtk_accel_label_get_type ()")]
- public class AccelLabel : Gtk.Label, Atk.Implementor, Gtk.Buildable {
- [CCode (has_construct_function = false, type = "GtkWidget*")]
- public AccelLabel (string str);
- public void get_accel (out uint accelerator_key, out Gdk.ModifierType accelerator_mods);
- public unowned Gtk.Widget get_accel_widget ();
- public uint get_accel_width ();
- public bool refetch ();
- public void set_accel (uint accelerator_key, Gdk.ModifierType accelerator_mods);
- public void set_accel_closure ([CCode (type = "GClosure*")] owned Gtk.AccelGroupActivate accel_closure);
- public void set_accel_widget (Gtk.Widget accel_widget);
- [NoAccessorMethod]
- public GLib.Closure accel_closure { owned get; set; }
- public Gtk.Widget accel_widget { get; set; }
- }
- [CCode (cheader_filename = "gtk/gtk.h", type_id = "gtk_accel_map_get_type ()")]
- public class AccelMap : GLib.Object {
- [CCode (has_construct_function = false)]
- protected AccelMap ();
- public static void add_entry (string accel_path, uint accel_key, Gdk.ModifierType accel_mods);
- public static void add_filter (string filter_pattern);
- public static bool change_entry (string accel_path, uint accel_key, Gdk.ModifierType accel_mods, bool replace);
- public static void @foreach (void* data, Gtk.AccelMapForeach foreach_func);
- public static void foreach_unfiltered (void* data, Gtk.AccelMapForeach foreach_func);
- public static unowned Gtk.AccelMap @get ();
- public static void load (string file_name);
- public static void load_fd (int fd);
- public static void load_scanner (GLib.Scanner scanner);
- public static void lock_path (string accel_path);
- public static bool lookup_entry (string accel_path, out Gtk.AccelKey key);
- public static void save (string file_name);
- public static void save_fd (int fd);
- public static void unlock_path (string accel_path);
- public virtual signal void changed (string p0, uint p1, Gdk.ModifierType p2);
- }
- [CCode (cheader_filename = "gtk/gtk.h")]
- [Compact]
- public class AccelMapClass {
- }
- [CCode (cheader_filename = "gtk/gtk.h", type_id = "gtk_accessible_get_type ()")]
- public class Accessible : Atk.Object {
- [CCode (has_construct_function = false)]
- protected Accessible ();
- [Deprecated (replacement = "Accessible.set_widget", since = "3.4")]
- public virtual void connect_widget_destroyed ();
- public unowned Gtk.Widget get_widget ();
- public void set_widget (Gtk.Widget widget);
- [NoWrapper]
- public virtual void widget_set ();
- [NoWrapper]
- public virtual void widget_unset ();
- public Gtk.Widget widget { get; set; }
- }
- [CCode (cheader_filename = "gtk/gtk.h", type_id = "gtk_action_get_type ()")]
- [Deprecated (replacement = "GLib.Action", since = "3.10")]
- public class Action : GLib.Object, Gtk.Buildable {
- [CCode (has_construct_function = false)]
- public Action (string name, string? label, string? tooltip, string? stock_id);
- public void block_activate ();
- public void connect_accelerator ();
- [NoWrapper]
- public virtual void connect_proxy (Gtk.Widget proxy);
- public unowned Gtk.Widget create_icon (Gtk.IconSize icon_size);
- public virtual unowned Gtk.Widget create_menu ();
- public virtual unowned Gtk.Widget create_menu_item ();
- public virtual unowned Gtk.Widget create_tool_item ();
- public void disconnect_accelerator ();
- [NoWrapper]
- public virtual void disconnect_proxy (Gtk.Widget proxy);
- public unowned GLib.Closure get_accel_closure ();
- public unowned string get_accel_path ();
- public bool get_always_show_image ();
- public unowned GLib.Icon get_gicon ();
- public unowned string get_icon_name ();
- public bool get_is_important ();
- public unowned string get_label ();
- public unowned GLib.SList get_proxies ();
- public bool get_sensitive ();
- public unowned string get_short_label ();
- public unowned string get_stock_id ();
- public unowned string get_tooltip ();
- public bool get_visible ();
- public bool get_visible_horizontal ();
- public bool get_visible_vertical ();
- public bool is_sensitive ();
- public bool is_visible ();
- public void set_accel_group (Gtk.AccelGroup accel_group);
- public void set_accel_path (string accel_path);
- public void set_always_show_image (bool always_show);
- public void set_gicon (GLib.Icon icon);
- public void set_icon_name (string icon_name);
- public void set_is_important (bool is_important);
- public void set_label (string label);
- public void set_sensitive (bool sensitive);
- public void set_short_label (string short_label);
- public void set_stock_id (string stock_id);
- public void set_tooltip (string tooltip);
- public void set_visible (bool visible);
- public void set_visible_horizontal (bool visible_horizontal);
- public void set_visible_vertical (bool visible_vertical);
- public void unblock_activate ();
- [NoAccessorMethod]
- public Gtk.ActionGroup action_group { owned get; set; }
- public bool always_show_image { get; set construct; }
- public GLib.Icon gicon { get; set; }
- [NoAccessorMethod]
- public bool hide_if_empty { get; set; }
- public string icon_name { get; set; }
- public bool is_important { get; set; }
- public string label { get; set; }
- public string name { get; construct; }
- public bool sensitive { get; set; }
- public string short_label { get; set; }
- public string stock_id { get; set; }
- public string tooltip { get; set; }
- public bool visible { get; set; }
- public bool visible_horizontal { get; set; }
- [NoAccessorMethod]
- public bool visible_overflown { get; set; }
- public bool visible_vertical { get; set; }
- [HasEmitter]
- public virtual signal void activate ();
- }
- [CCode (cheader_filename = "gtk/gtk.h", type_id = "gtk_action_bar_get_type ()")]
- public class ActionBar : Gtk.Bin, Atk.Implementor, Gtk.Buildable {
- [CCode (has_construct_function = false, type = "GtkWidget*")]
- public ActionBar ();
- public unowned Gtk.Widget get_center_widget ();
- public void pack_end (Gtk.Widget child);
- public void pack_start (Gtk.Widget child);
- public void set_center_widget (Gtk.Widget? center_widget);
- }
- [CCode (cheader_filename = "gtk/gtk.h", type_id = "gtk_action_group_get_type ()")]
- [Deprecated (since = "3.10")]
- public class ActionGroup : GLib.Object, Gtk.Buildable {
- [CCode (has_construct_function = false)]
- public ActionGroup (string name);
- public void add_action (Gtk.Action action);
- public void add_action_with_accel (Gtk.Action action, string? accelerator);
- public void add_actions (Gtk.ActionEntry[] entries, void* user_data);
- public void add_actions_full (Gtk.ActionEntry[] entries, void* user_data, GLib.DestroyNotify? destroy);
- public void add_radio_actions (Gtk.RadioActionEntry[] entries, int value, [CCode (type = "GCallback")] Gtk.RadioActionCallback on_change);
- public void add_radio_actions_full (Gtk.RadioActionEntry[] entries, int value, [CCode (type = "GCallback")] Gtk.RadioActionCallback on_change, GLib.DestroyNotify? destroy);
- public void add_toggle_actions (Gtk.ToggleActionEntry[] entries, void* user_data);
- public void add_toggle_actions_full (Gtk.ToggleActionEntry[] entries, void* user_data, GLib.DestroyNotify? destroy);
- public unowned Gtk.AccelGroup get_accel_group ();
- public virtual unowned Gtk.Action get_action (string action_name);
- public bool get_sensitive ();
- public bool get_visible ();
- public GLib.List list_actions ();
- public void remove_action (Gtk.Action action);
- public void set_accel_group (Gtk.AccelGroup accel_group);
- public void set_sensitive (bool sensitive);
- public void set_translate_func (owned Gtk.TranslateFunc func);
- public void set_translation_domain (string domain);
- public void set_visible (bool visible);
- public unowned string translate_string (string str);
- public Gtk.AccelGroup accel_group { get; set; }
- public string name { get; construct; }
- public bool sensitive { get; set; }
- public bool visible { get; set; }
- public virtual signal void connect_proxy (Gtk.Action p0, Gtk.Widget p1);
- public virtual signal void disconnect_proxy (Gtk.Action p0, Gtk.Widget p1);
- public virtual signal void post_activate (Gtk.Action p0);
- public virtual signal void pre_activate (Gtk.Action p0);
- }
- [CCode (cheader_filename = "gtk/gtk.h", type_id = "gtk_adjustment_get_type ()")]
- public class Adjustment : GLib.InitiallyUnowned {
- [CCode (has_construct_function = false)]
- public Adjustment (double value, double lower, double upper, double step_increment, double page_increment, double page_size);
- public void clamp_page (double lower, double upper);
- public void configure (double value, double lower, double upper, double step_increment, double page_increment, double page_size);
- public double get_lower ();
- public double get_minimum_increment ();
- public double get_page_increment ();
- public double get_page_size ();
- public double get_step_increment ();
- public double get_upper ();
- public double get_value ();
- public void set_lower (double lower);
- public void set_page_increment (double page_increment);
- public void set_page_size (double page_size);
- public void set_step_increment (double step_increment);
- public void set_upper (double upper);
- public void set_value (double value);
- public double lower { get; set; }
- public double page_increment { get; set; }
- public double page_size { get; set; }
- public double step_increment { get; set; }
- public double upper { get; set; }
- public double value { get; set; }
- [HasEmitter]
- public virtual signal void changed ();
- [HasEmitter]
- public virtual signal void value_changed ();
- }
- [CCode (cheader_filename = "gtk/gtk.h", type_id = "gtk_alignment_get_type ()")]
- public class Alignment : Gtk.Bin, Atk.Implementor, Gtk.Buildable {
- [CCode (has_construct_function = false, type = "GtkWidget*")]
- public Alignment (float xalign, float yalign, float xscale, float yscale);
- public void get_padding (out uint padding_top, out uint padding_bottom, out uint padding_left, out uint padding_right);
- public void @set (float xalign, float yalign, float xscale, float yscale);
- public void set_padding (uint padding_top, uint padding_bottom, uint padding_left, uint padding_right);
- [NoAccessorMethod]
- public uint bottom_padding { get; set; }
- [NoAccessorMethod]
- public uint left_padding { get; set; }
- [NoAccessorMethod]
- public uint right_padding { get; set; }
- [NoAccessorMethod]
- public uint top_padding { get; set; }
- [NoAccessorMethod]
- public float xalign { get; set; }
- [NoAccessorMethod]
- public float xscale { get; set; }
- [NoAccessorMethod]
- public float yalign { get; set; }
- [NoAccessorMethod]
- public float yscale { get; set; }
- }
- [CCode (cheader_filename = "gtk/gtk.h", type_id = "gtk_app_chooser_button_get_type ()")]
- public class AppChooserButton : Gtk.ComboBox, Atk.Implementor, Gtk.Buildable, Gtk.CellLayout, Gtk.CellEditable, Gtk.AppChooser {
- [CCode (has_construct_function = false, type = "GtkWidget*")]
- public AppChooserButton (string content_type);
- public void append_custom_item (string name, string label, GLib.Icon icon);
- public void append_separator ();
- public unowned string get_heading ();
- public bool get_show_default_item ();
- public bool get_show_dialog_item ();
- public void set_active_custom_item (string name);
- public void set_heading (string heading);
- public void set_show_default_item (bool setting);
- public void set_show_dialog_item (bool setting);
- public string heading { get; set; }
- public bool show_default_item { get; set construct; }
- public bool show_dialog_item { get; set construct; }
- public virtual signal void custom_item_activated (string item_name);
- }
- [CCode (cheader_filename = "gtk/gtk.h", type_id = "gtk_app_chooser_dialog_get_type ()")]
- public class AppChooserDialog : Gtk.Dialog, Atk.Implementor, Gtk.Buildable, Gtk.AppChooser {
- [CCode (has_construct_function = false, type = "GtkWidget*")]
- public AppChooserDialog (Gtk.Window parent, Gtk.DialogFlags flags, GLib.File file);
- [CCode (has_construct_function = false, type = "GtkWidget*")]
- public AppChooserDialog.for_content_type (Gtk.Window parent, Gtk.DialogFlags flags, string content_type);
- public unowned string get_heading ();
- public unowned Gtk.Widget get_widget ();
- public void set_heading (string heading);
- [NoAccessorMethod]
- public GLib.File gfile { owned get; construct; }
- public string heading { get; set; }
- }
- [CCode (cheader_filename = "gtk/gtk.h", type_id = "gtk_app_chooser_widget_get_type ()")]
- public class AppChooserWidget : Gtk.Box, Atk.Implementor, Gtk.Buildable, Gtk.Orientable, Gtk.AppChooser {
- [CCode (has_construct_function = false, type = "GtkWidget*")]
- public AppChooserWidget (string content_type);
- public unowned string get_default_text ();
- public bool get_show_all ();
- public bool get_show_default ();
- public bool get_show_fallback ();
- public bool get_show_other ();
- public bool get_show_recommended ();
- public void set_default_text (string text);
- public void set_show_all (bool setting);
- public void set_show_default (bool setting);
- public void set_show_fallback (bool setting);
- public void set_show_other (bool setting);
- public void set_show_recommended (bool setting);
- public string default_text { get; set; }
- public bool show_all { get; set construct; }
- public bool show_default { get; set construct; }
- public bool show_fallback { get; set construct; }
- public bool show_other { get; set construct; }
- public bool show_recommended { get; set construct; }
- public virtual signal void application_activated (GLib.AppInfo app_info);
- public virtual signal void application_selected (GLib.AppInfo app_info);
- public virtual signal void populate_popup (Gtk.Menu menu, GLib.AppInfo app_info);
- }
- [CCode (cheader_filename = "gtk/gtk.h", type_id = "gtk_application_get_type ()")]
- public class Application : GLib.Application, GLib.ActionGroup, GLib.ActionMap {
- [CCode (has_construct_function = false)]
- public Application (string application_id, GLib.ApplicationFlags flags);
- public void add_accelerator (string accelerator, string action_name, GLib.Variant? parameter);
- public void add_window (Gtk.Window window);
- [CCode (array_length = false, array_null_terminated = true)]
- public string[] get_accels_for_action (string detailed_action_name);
- [CCode (array_length = false, array_null_terminated = true)]
- public string[] get_actions_for_accel (string accel);
- public unowned Gtk.Window get_active_window ();
- public unowned GLib.MenuModel get_app_menu ();
- public unowned GLib.Menu get_menu_by_id (string id);
- public unowned GLib.MenuModel get_menubar ();
- public unowned Gtk.Window get_window_by_id (uint id);
- public unowned GLib.List get_windows ();
- public uint inhibit (Gtk.Window? window, Gtk.ApplicationInhibitFlags flags, string? reason);
- public bool is_inhibited (Gtk.ApplicationInhibitFlags flags);
- [CCode (array_length = false, array_null_terminated = true)]
- public string[] list_action_descriptions ();
- public bool prefers_app_menu ();
- public void remove_accelerator (string action_name, GLib.Variant? parameter);
- public void remove_window (Gtk.Window window);
- public void set_accels_for_action (string detailed_action_name, [CCode (array_length = false, array_null_terminated = true)] string[] accels);
- public void set_app_menu (GLib.MenuModel app_menu);
- public void set_menubar (GLib.MenuModel menubar);
- public void uninhibit (uint cookie);
- public Gtk.Window active_window { get; }
- public GLib.MenuModel app_menu { get; set; }
- public GLib.MenuModel menubar { get; set; }
- [NoAccessorMethod]
- public bool register_session { get; set; }
- public virtual signal void window_added (Gtk.Window window);
- public virtual signal void window_removed (Gtk.Window window);
- }
- [CCode (cheader_filename = "gtk/gtk.h", type_id = "gtk_application_window_get_type ()")]
- public class ApplicationWindow : Gtk.Window, Atk.Implementor, Gtk.Buildable, GLib.ActionGroup, GLib.ActionMap {
- [CCode (has_construct_function = false, type = "GtkWidget*")]
- public ApplicationWindow (Gtk.Application application);
- public uint get_id ();
- public bool get_show_menubar ();
- public void set_show_menubar (bool show_menubar);
- public bool show_menubar { get; set construct; }
- }
- [CCode (cheader_filename = "gtk/gtk.h", type_id = "gtk_arrow_get_type ()")]
- public class Arrow : Gtk.Misc, Atk.Implementor, Gtk.Buildable {
- [CCode (has_construct_function = false, type = "GtkWidget*")]
- public Arrow (Gtk.ArrowType arrow_type, Gtk.ShadowType shadow_type);
- public void @set (Gtk.ArrowType arrow_type, Gtk.ShadowType shadow_type);
- [NoAccessorMethod]
- public Gtk.ArrowType arrow_type { get; set; }
- [NoAccessorMethod]
- public Gtk.ShadowType shadow_type { get; set; }
- }
- [CCode (cheader_filename = "gtk/gtk.h", type_id = "gtk_arrow_accessible_get_type ()")]
- public class ArrowAccessible : Gtk.WidgetAccessible, Atk.Component, Atk.Image {
- [CCode (has_construct_function = false)]
- protected ArrowAccessible ();
- }
- [CCode (cheader_filename = "gtk/gtk.h", type_id = "gtk_aspect_frame_get_type ()")]
- public class AspectFrame : Gtk.Frame, Atk.Implementor, Gtk.Buildable {
- [CCode (has_construct_function = false, type = "GtkWidget*")]
- public AspectFrame (string? label, float xalign, float yalign, float ratio, bool obey_child);
- public void @set (float xalign, float yalign, float ratio, bool obey_child);
- [NoAccessorMethod]
- public bool obey_child { get; set; }
- [NoAccessorMethod]
- public float ratio { get; set; }
- [NoAccessorMethod]
- public float xalign { get; set; }
- [NoAccessorMethod]
- public float yalign { get; set; }
- }
- [CCode (cheader_filename = "gtk/gtk.h", type_id = "gtk_assistant_get_type ()")]
- public class Assistant : Gtk.Window, Atk.Implementor, Gtk.Buildable {
- [CCode (has_construct_function = false, type = "GtkWidget*")]
- public Assistant ();
- public void add_action_widget (Gtk.Widget child);
- public int append_page (Gtk.Widget page);
- public void commit ();
- public int get_current_page ();
- public int get_n_pages ();
- public unowned Gtk.Widget get_nth_page (int page_num);
- public bool get_page_complete (Gtk.Widget page);
- [Deprecated (since = "3.2")]
- public unowned Gdk.Pixbuf get_page_header_image (Gtk.Widget page);
- [Deprecated (since = "3.2")]
- public unowned Gdk.Pixbuf get_page_side_image (Gtk.Widget page);
- public unowned string get_page_title (Gtk.Widget page);
- public Gtk.AssistantPageType get_page_type (Gtk.Widget page);
- public int insert_page (Gtk.Widget page, int position);
- public void next_page ();
- public int prepend_page (Gtk.Widget page);
- public void previous_page ();
- public void remove_action_widget (Gtk.Widget child);
- public void remove_page (int page_num);
- public void set_current_page (int page_num);
- public void set_forward_page_func (owned Gtk.AssistantPageFunc page_func);
- public void set_page_complete (Gtk.Widget page, bool complete);
- [Deprecated (since = "3.2")]
- public void set_page_header_image (Gtk.Widget page, Gdk.Pixbuf pixbuf);
- [Deprecated (since = "3.2")]
- public void set_page_side_image (Gtk.Widget page, Gdk.Pixbuf pixbuf);
- public void set_page_title (Gtk.Widget page, string title);
- public void set_page_type (Gtk.Widget page, Gtk.AssistantPageType type);
- public void update_buttons_state ();
- [NoAccessorMethod]
- public int use_header_bar { get; construct; }
- public virtual signal void apply ();
- public virtual signal void cancel ();
- public virtual signal void close ();
- public virtual signal void escape ();
- public virtual signal void prepare (Gtk.Widget page);
- }
- [CCode (cheader_filename = "gtk/gtk.h", type_id = "gtk_bin_get_type ()")]
- public abstract class Bin : Gtk.Container, Atk.Implementor, Gtk.Buildable {
- [CCode (has_construct_function = false)]
- protected Bin ();
- public unowned Gtk.Widget get_child ();
- }
- [CCode (cheader_filename = "gtk/gtk.h")]
- [Compact]
- public class BindingEntry {
- public weak Gtk.BindingSet binding_set;
- public uint destroyed;
- public weak Gtk.BindingEntry hash_next;
- public uint in_emission;
- public uint keyval;
- public uint marks_unbound;
- public Gdk.ModifierType modifiers;
- public weak Gtk.BindingEntry set_next;
- public weak Gtk.BindingSignal signals;
- public static void add_signal (Gtk.BindingSet binding_set, uint keyval, Gdk.ModifierType modifiers, string signal_name, uint n_args, ...);
- public static GLib.TokenType add_signal_from_string (Gtk.BindingSet binding_set, string signal_desc);
- public static void add_signall (Gtk.BindingSet binding_set, uint keyval, Gdk.ModifierType modifiers, string signal_name, GLib.SList binding_args);
- public static void remove (Gtk.BindingSet binding_set, uint keyval, Gdk.ModifierType modifiers);
- public static void skip (Gtk.BindingSet binding_set, uint keyval, Gdk.ModifierType modifiers);
- }
- [CCode (cheader_filename = "gtk/gtk.h")]
- [Compact]
- public class BindingSet {
- public weak Gtk.BindingEntry current;
- public weak Gtk.BindingEntry entries;
- public uint parsed;
- public int priority;
- public weak string set_name;
- public bool activate (uint keyval, Gdk.ModifierType modifiers, GLib.Object object);
- [Deprecated (since = "3.0")]
- public void add_path (Gtk.PathType path_type, string path_pattern, Gtk.PathPriorityType priority);
- public static unowned Gtk.BindingSet by_class (GLib.ObjectClass object_class);
- public static unowned Gtk.BindingSet find (string set_name);
- public static unowned Gtk.BindingSet @new (string name);
- }
- [CCode (cheader_filename = "gtk/gtk.h")]
- [Compact]
- public class BindingSignal {
- [CCode (array_length_cname = "n_args")]
- public weak Gtk.BindingArg[] args;
- public uint n_args;
- public weak Gtk.BindingSignal next;
- public weak string signal_name;
- }
- [CCode (cheader_filename = "gtk/gtk.h", type_id = "gtk_boolean_cell_accessible_get_type ()")]
- public class BooleanCellAccessible : Gtk.RendererCellAccessible, Atk.Action, Atk.Component {
- [CCode (has_construct_function = false)]
- protected BooleanCellAccessible ();
- }
- [CCode (cheader_filename = "gtk/gtk.h", type_id = "gtk_box_get_type ()")]
- public class Box : Gtk.Container, Atk.Implementor, Gtk.Buildable, Gtk.Orientable {
- [CCode (has_construct_function = false, type = "GtkWidget*")]
- public Box (Gtk.Orientation orientation, int spacing);
- public Gtk.BaselinePosition get_baseline_position ();
- public unowned Gtk.Widget get_center_widget ();
- public bool get_homogeneous ();
- public int get_spacing ();
- public void pack_end (Gtk.Widget child, bool expand = true, bool fill = true, uint padding = 0);
- public void pack_start (Gtk.Widget child, bool expand = true, bool fill = true, uint padding = 0);
- public void query_child_packing (Gtk.Widget child, out bool expand, out bool fill, out uint padding, out Gtk.PackType pack_type);
- public void reorder_child (Gtk.Widget child, int position);
- public void set_baseline_position (Gtk.BaselinePosition position);
- public void set_center_widget (Gtk.Widget widget);
- public void set_child_packing (Gtk.Widget child, bool expand, bool fill, uint padding, Gtk.PackType pack_type);
- public void set_homogeneous (bool homogeneous);
- public void set_spacing (int spacing);
- public Gtk.BaselinePosition baseline_position { get; set; }
- public bool homogeneous { get; set; }
- public int spacing { get; set; }
- }
- [CCode (cheader_filename = "gtk/gtk.h", type_id = "gtk_builder_get_type ()")]
- public class Builder : GLib.Object {
- [CCode (has_construct_function = false)]
- public Builder ();
- public void add_callback_symbol (string callback_name, GLib.Callback callback_symbol);
- public void add_callback_symbols (string first_callback_name, ...);
- public uint add_from_file (string filename) throws GLib.Error;
- public uint add_from_resource (string resource_path) throws GLib.Error;
- public uint add_from_string (string buffer, size_t length) throws GLib.Error;
- public uint add_objects_from_file (string filename, [CCode (array_length = false, array_null_terminated = true)] string[] object_ids) throws GLib.Error;
- public uint add_objects_from_resource (string resource_path, [CCode (array_length = false, array_null_terminated = true)] string[] object_ids) throws GLib.Error;
- public uint add_objects_from_string (string buffer, size_t length, [CCode (array_length = false, array_null_terminated = true)] string[] object_ids) throws GLib.Error;
- public void connect_signals (void* user_data);
- public void connect_signals_full (Gtk.BuilderConnectFunc func);
- public static GLib.Quark error_quark ();
- public void expose_object (string name, GLib.Object object);
- [CCode (has_construct_function = false)]
- public Builder.from_file (string filename);
- [CCode (has_construct_function = false)]
- public Builder.from_resource (string resource_path);
- [CCode (has_construct_function = false)]
- public Builder.from_string (string str, ssize_t length);
- public unowned Gtk.Application get_application ();
- public unowned GLib.Object get_object (string name);
- public GLib.SList get_objects ();
- public unowned string get_translation_domain ();
- public virtual GLib.Type get_type_from_name (string type_name);
- public unowned GLib.Callback lookup_callback_symbol (string callback_name);
- public void set_application (Gtk.Application application);
- public void set_translation_domain (string domain);
- public bool value_from_string (GLib.ParamSpec pspec, string str, out GLib.Value value) throws GLib.Error;
- public bool value_from_string_type (GLib.Type type, string str, out GLib.Value value) throws GLib.Error;
- public string translation_domain { get; set; }
- }
- [CCode (cheader_filename = "gtk/gtk.h", type_id = "gtk_button_get_type ()")]
- public class Button : Gtk.Bin, Atk.Implementor, Gtk.Buildable, Gtk.Actionable, Gtk.Activatable {
- [CCode (has_construct_function = false, type = "GtkWidget*")]
- public Button ();
- [CCode (has_construct_function = false, type = "GtkWidget*")]
- public Button.from_icon_name (string icon_name, Gtk.IconSize size);
- [CCode (has_construct_function = false, type = "GtkWidget*")]
- public Button.from_stock (string stock_id);
- public void get_alignment (out float xalign, out float yalign);
- public bool get_always_show_image ();
- public unowned Gdk.Window get_event_window ();
- public bool get_focus_on_click ();
- public unowned Gtk.Widget get_image ();
- public Gtk.PositionType get_image_position ();
- public unowned string get_label ();
- public Gtk.ReliefStyle get_relief ();
- public bool get_use_stock ();
- public bool get_use_underline ();
- public void set_alignment (float xalign, float yalign);
- public void set_always_show_image (bool always_show);
- public void set_focus_on_click (bool focus_on_click);
- public void set_image (Gtk.Widget image);
- public void set_image_position (Gtk.PositionType position);
- public void set_label (string? label);
- public void set_relief (Gtk.ReliefStyle relief);
- public void set_use_stock (bool use_stock);
- public void set_use_underline (bool use_underline);
- [CCode (has_construct_function = false, type = "GtkWidget*")]
- public Button.with_label (string label);
- [CCode (has_construct_function = false, type = "GtkWidget*")]
- public Button.with_mnemonic (string label);
- public bool always_show_image { get; set construct; }
- public bool focus_on_click { get; set; }
- public Gtk.Widget image { get; set; }
- public Gtk.PositionType image_position { get; set; }
- public string label { get; set construct; }
- public Gtk.ReliefStyle relief { get; set; }
- public bool use_stock { get; set construct; }
- public bool use_underline { get; set construct; }
- [NoAccessorMethod]
- public float xalign { get; set; }
- [NoAccessorMethod]
- public float yalign { get; set; }
- public virtual signal void activate ();
- [HasEmitter]
- public virtual signal void clicked ();
- [Deprecated (replacement = "Gtk.Widget.enter_notify_event", since = "2.8")]
- [HasEmitter]
- public virtual signal void enter ();
- [Deprecated (replacement = "Gtk.Widget.leave_notify_event", since = "2.8")]
- [HasEmitter]
- public virtual signal void leave ();
- [Deprecated (replacement = "Gtk.Widget.button_press_event", since = "2.8")]
- [HasEmitter]
- public virtual signal void pressed ();
- [Deprecated (replacement = "Gtk.Widget.button_release_event", since = "2.8")]
- [HasEmitter]
- public virtual signal void released ();
- }
- [CCode (cheader_filename = "gtk/gtk.h", type_id = "gtk_button_accessible_get_type ()")]
- public class ButtonAccessible : Gtk.ContainerAccessible, Atk.Component, Atk.Action, Atk.Image {
- [CCode (has_construct_function = false)]
- protected ButtonAccessible ();
- }
- [CCode (cheader_filename = "gtk/gtk.h", type_id = "gtk_button_box_get_type ()")]
- public class ButtonBox : Gtk.Box, Atk.Implementor, Gtk.Buildable, Gtk.Orientable {
- [CCode (has_construct_function = false, type = "GtkWidget*")]
- public ButtonBox (Gtk.Orientation orientation);
- public bool get_child_non_homogeneous (Gtk.Widget child);
- public bool get_child_secondary (Gtk.Widget child);
- public Gtk.ButtonBoxStyle get_layout ();
- public void set_child_non_homogeneous (Gtk.Widget child, bool non_homogeneous);
- public void set_child_secondary (Gtk.Widget child, bool is_secondary);
- public void set_layout (Gtk.ButtonBoxStyle layout_style);
- [NoAccessorMethod]
- public Gtk.ButtonBoxStyle layout_style { get; set; }
- }
- [CCode (cheader_filename = "gtk/gtk.h", type_id = "gtk_calendar_get_type ()")]
- public class Calendar : Gtk.Widget, Atk.Implementor, Gtk.Buildable {
- [CCode (has_construct_function = false, type = "GtkWidget*")]
- public Calendar ();
- public void clear_marks ();
- public void get_date (out uint year, out uint month, out uint day);
- public bool get_day_is_marked (uint day);
- public int get_detail_height_rows ();
- public int get_detail_width_chars ();
- public Gtk.CalendarDisplayOptions get_display_options ();
- public void mark_day (uint day);
- public void select_day (uint day);
- public void select_month (uint month, uint year);
- public void set_detail_func (owned Gtk.CalendarDetailFunc func);
- public void set_detail_height_rows (int rows);
- public void set_detail_width_chars (int chars);
- public void set_display_options (Gtk.CalendarDisplayOptions flags);
- public void unmark_day (uint day);
- [NoAccessorMethod]
- public int day { get; set; }
- public int detail_height_rows { get; set; }
- public int detail_width_chars { get; set; }
- [NoAccessorMethod]
- public int month { get; set; }
- [NoAccessorMethod]
- public bool no_month_change { get; set; }
- [NoAccessorMethod]
- public bool show_day_names { get; set; }
- [NoAccessorMethod]
- public bool show_details { get; set; }
- [NoAccessorMethod]
- public bool show_heading { get; set; }
- [NoAccessorMethod]
- public bool show_week_numbers { get; set; }
- [NoAccessorMethod]
- public int year { get; set; }
- public virtual signal void day_selected ();
- public virtual signal void day_selected_double_click ();
- public virtual signal void month_changed ();
- public virtual signal void next_month ();
- public virtual signal void next_year ();
- public virtual signal void prev_month ();
- public virtual signal void prev_year ();
- }
- [CCode (cheader_filename = "gtk/gtk.h", type_id = "gtk_cell_accessible_get_type ()")]
- public class CellAccessible : Gtk.Accessible, Atk.Action, Atk.Component {
- [CCode (has_construct_function = false)]
- protected CellAccessible ();
- [NoWrapper]
- public virtual void update_cache ();
- }
- [CCode (cheader_filename = "gtk/gtk.h", type_id = "gtk_cell_area_get_type ()")]
- public abstract class CellArea : GLib.InitiallyUnowned, Gtk.CellLayout, Gtk.Buildable {
- [CCode (has_construct_function = false)]
- protected CellArea ();
- public virtual bool activate (Gtk.CellAreaContext context, Gtk.Widget widget, Gdk.Rectangle cell_area, Gtk.CellRendererState flags, bool edit_only);
- public bool activate_cell (Gtk.Widget widget, Gtk.CellRenderer renderer, Gdk.Event event, Gdk.Rectangle cell_area, Gtk.CellRendererState flags);
- public virtual void add (Gtk.CellRenderer renderer);
- public void add_focus_sibling (Gtk.CellRenderer renderer, Gtk.CellRenderer sibling);
- public void add_with_properties (Gtk.CellRenderer renderer, ...);
- public void attribute_connect (Gtk.CellRenderer renderer, string attribute, int column);
- public void attribute_disconnect (Gtk.CellRenderer renderer, string attribute);
- public int attribute_get_column (Gtk.CellRenderer renderer, string attribute);
- public void cell_get (Gtk.CellRenderer renderer, ...);
- public void cell_get_property (Gtk.CellRenderer renderer, string property_name, GLib.Value value);
- public void cell_get_valist (Gtk.CellRenderer renderer, string first_property_name, va_list var_args);
- public void cell_set (Gtk.CellRenderer renderer, ...);
- public void cell_set_property (Gtk.CellRenderer renderer, string property_name, GLib.Value value);
- public void cell_set_valist (Gtk.CellRenderer renderer, string first_property_name, va_list var_args);
- public virtual Gtk.CellAreaContext copy_context (Gtk.CellAreaContext context);
- public virtual Gtk.CellAreaContext create_context ();
- public virtual int event (Gtk.CellAreaContext context, Gtk.Widget widget, Gdk.Event event, Gdk.Rectangle cell_area, Gtk.CellRendererState flags);
- [CCode (cname = "gtk_cell_area_class_find_cell_property")]
- public class unowned GLib.ParamSpec find_cell_property (string property_name);
- public virtual bool focus (Gtk.DirectionType direction);
- public virtual void @foreach (Gtk.CellCallback callback);
- public virtual void foreach_alloc (Gtk.CellAreaContext context, Gtk.Widget widget, Gdk.Rectangle cell_area, Gdk.Rectangle background_area, Gtk.CellAllocCallback callback);
- public Gdk.Rectangle get_cell_allocation (Gtk.CellAreaContext context, Gtk.Widget widget, Gtk.CellRenderer renderer, Gdk.Rectangle cell_area);
- public unowned Gtk.CellRenderer get_cell_at_position (Gtk.CellAreaContext context, Gtk.Widget widget, Gdk.Rectangle cell_area, int x, int y, out Gdk.Rectangle alloc_area);
- [NoWrapper]
- public virtual void get_cell_property (Gtk.CellRenderer renderer, uint property_id, GLib.Value value, GLib.ParamSpec pspec);
- public unowned string get_current_path_string ();
- public unowned Gtk.CellEditable get_edit_widget ();
- public unowned Gtk.CellRenderer get_edited_cell ();
- public unowned Gtk.CellRenderer get_focus_cell ();
- public unowned Gtk.CellRenderer get_focus_from_sibling (Gtk.CellRenderer renderer);
- public unowned GLib.List get_focus_siblings (Gtk.CellRenderer renderer);
- public virtual void get_preferred_height (Gtk.CellAreaContext context, Gtk.Widget widget, out int minimum_height, out int natural_height);
- public virtual void get_preferred_height_for_width (Gtk.CellAreaContext context, Gtk.Widget widget, int width, out int minimum_height, out int natural_height);
- public virtual void get_preferred_width (Gtk.CellAreaContext context, Gtk.Widget widget, out int minimum_width, out int natural_width);
- public virtual void get_preferred_width_for_height (Gtk.CellAreaContext context, Gtk.Widget widget, int height, out int minimum_width, out int natural_width);
- public virtual Gtk.SizeRequestMode get_request_mode ();
- public bool has_renderer (Gtk.CellRenderer renderer);
- public Gdk.Rectangle inner_cell_area (Gtk.Widget widget, Gdk.Rectangle cell_area);
- [CCode (cname = "gtk_cell_area_class_install_cell_property")]
- public class void install_cell_property (uint property_id, GLib.ParamSpec pspec);
- public virtual bool is_activatable ();
- public bool is_focus_sibling (Gtk.CellRenderer renderer, Gtk.CellRenderer sibling);
- [CCode (cname = "gtk_cell_area_class_list_cell_properties")]
- public class unowned GLib.ParamSpec list_cell_properties (uint n_properties);
- public virtual void remove (Gtk.CellRenderer renderer);
- public void remove_focus_sibling (Gtk.CellRenderer renderer, Gtk.CellRenderer sibling);
- public virtual void render (Gtk.CellAreaContext context, Gtk.Widget widget, Cairo.Context cr, Gdk.Rectangle background_area, Gdk.Rectangle cell_area, Gtk.CellRendererState flags, bool paint_focus);
- public void request_renderer (Gtk.CellRenderer renderer, Gtk.Orientation orientation, Gtk.Widget widget, int for_size, out int minimum_size, out int natural_size);
- [NoWrapper]
- public virtual void set_cell_property (Gtk.CellRenderer renderer, uint property_id, GLib.Value value, GLib.ParamSpec pspec);
- public void set_focus_cell (Gtk.CellRenderer renderer);
- public void stop_editing (bool canceled);
- public Gtk.CellEditable edit_widget { get; }
- public Gtk.CellRenderer edited_cell { get; }
- public Gtk.CellRenderer focus_cell { get; set; }
- public virtual signal void add_editable (Gtk.CellRenderer p0, Gtk.CellEditable p1, Gdk.Rectangle p2, string p3);
- [HasEmitter]
- public virtual signal void apply_attributes (Gtk.TreeModel tree_model, Gtk.TreeIter iter, bool is_expander, bool is_expanded);
- public virtual signal void focus_changed (Gtk.CellRenderer p0, string p1);
- public virtual signal void remove_editable (Gtk.CellRenderer p0, Gtk.CellEditable p1);
- }
- [CCode (cheader_filename = "gtk/gtk.h", type_id = "gtk_cell_area_box_get_type ()")]
- public class CellAreaBox : Gtk.CellArea, Gtk.CellLayout, Gtk.Buildable, Gtk.Orientable {
- [CCode (has_construct_function = false, type = "GtkCellArea*")]
- public CellAreaBox ();
- public int get_spacing ();
- public void set_spacing (int spacing);
- public int spacing { get; set; }
- }
- [CCode (cheader_filename = "gtk/gtk.h", type_id = "gtk_cell_area_context_get_type ()")]
- public class CellAreaContext : GLib.Object {
- [CCode (has_construct_function = false)]
- protected CellAreaContext ();
- public virtual void allocate (int width, int height);
- public void get_allocation (out int width, out int height);
- public unowned Gtk.CellArea get_area ();
- public void get_preferred_height (out int minimum_height, out int natural_height);
- public virtual void get_preferred_height_for_width (int width, out int minimum_height, out int natural_height);
- public void get_preferred_width (out int minimum_width, out int natural_width);
- public virtual void get_preferred_width_for_height (int height, out int minimum_width, out int natural_width);
- public void push_preferred_height (int minimum_height, int natural_height);
- public void push_preferred_width (int minimum_width, int natural_width);
- public virtual void reset ();
- public Gtk.CellArea area { get; construct; }
- [NoAccessorMethod]
- public int minimum_height { get; }
- [NoAccessorMethod]
- public int minimum_width { get; }
- [NoAccessorMethod]
- public int natural_height { get; }
- [NoAccessorMethod]
- public int natural_width { get; }
- }
- [CCode (cheader_filename = "gtk/gtk.h", type_id = "gtk_cell_renderer_get_type ()")]
- public abstract class CellRenderer : GLib.InitiallyUnowned {
- [CCode (has_construct_function = false)]
- protected CellRenderer ();
- public virtual bool activate (Gdk.Event event, Gtk.Widget widget, string path, Gdk.Rectangle background_area, Gdk.Rectangle cell_area, Gtk.CellRendererState flags);
- public virtual Gdk.Rectangle get_aligned_area (Gtk.Widget widget, Gtk.CellRendererState flags, Gdk.Rectangle cell_area);
- public void get_alignment (out float xalign, out float yalign);
- public void get_fixed_size (out int width, out int height);
- public void get_padding (out int xpad, out int ypad);
- public virtual void get_preferred_height (Gtk.Widget widget, out int minimum_size, out int natural_size);
- public virtual void get_preferred_height_for_width (Gtk.Widget widget, int width, out int minimum_height, out int natural_height);
- public void get_preferred_size (Gtk.Widget widget, out Gtk.Requisition minimum_size, out Gtk.Requisition natural_size);
- public virtual void get_preferred_width (Gtk.Widget widget, out int minimum_size, out int natural_size);
- public virtual void get_preferred_width_for_height (Gtk.Widget widget, int height, out int minimum_width, out int natural_width);
- public virtual Gtk.SizeRequestMode get_request_mode ();
- public bool get_sensitive ();
- [Deprecated (replacement = "get_preferred_size", since = "3.0")]
- public abstract void get_size (Gtk.Widget widget, Gdk.Rectangle? cell_area, out int x_offset, out int y_offset, out int width, out int height);
- public Gtk.StateFlags get_state (Gtk.Widget widget, Gtk.CellRendererState cell_state);
- public bool get_visible ();
- public bool is_activatable ();
- public abstract void render (Cairo.Context cr, Gtk.Widget widget, Gdk.Rectangle background_area, Gdk.Rectangle cell_area, Gtk.CellRendererState flags);
- [CCode (cname = "gtk_cell_renderer_class_set_accessible_type")]
- public class void set_accessible_type (GLib.Type type);
- public void set_alignment (float xalign, float yalign);
- public void set_fixed_size (int width, int height);
- public void set_padding (int xpad, int ypad);
- public void set_sensitive (bool sensitive);
- public void set_visible (bool visible);
- public virtual unowned Gtk.CellEditable start_editing (Gdk.Event event, Gtk.Widget widget, string path, Gdk.Rectangle background_area, Gdk.Rectangle cell_area, Gtk.CellRendererState flags);
- public void stop_editing (bool canceled);
- [NoAccessorMethod]
- public string cell_background { set; }
- [Deprecated (replacement = "Gtk.CellRenderer.cell_background_rgba", since = "3.4")]
- [NoAccessorMethod]
- public Gdk.Color cell_background_gdk { get; set; }
- [NoAccessorMethod]
- public Gdk.RGBA cell_background_rgba { get; set; }
- [NoAccessorMethod]
- public bool cell_background_set { get; set; }
- [NoAccessorMethod]
- public bool editing { get; }
- [NoAccessorMethod]
- public int height { get; set; }
- [NoAccessorMethod]
- public bool is_expanded { get; set; }
- [NoAccessorMethod]
- public bool is_expander { get; set; }
- [NoAccessorMethod]
- public Gtk.CellRendererMode mode { get; set; }
- public bool sensitive { get; set; }
- public bool visible { get; set; }
- [NoAccessorMethod]
- public int width { get; set; }
- [NoAccessorMethod]
- public float xalign { get; set; }
- [NoAccessorMethod]
- public uint xpad { get; set; }
- [NoAccessorMethod]
- public float yalign { get; set; }
- [NoAccessorMethod]
- public uint ypad { get; set; }
- [HasEmitter]
- public virtual signal void editing_canceled ();
- public virtual signal void editing_started (Gtk.CellEditable editable, string path);
- }
- [CCode (cheader_filename = "gtk/gtk.h", type_id = "gtk_cell_renderer_accel_get_type ()")]
- public class CellRendererAccel : Gtk.CellRendererText {
- [CCode (has_construct_function = false, type = "GtkCellRenderer*")]
- public CellRendererAccel ();
- [NoAccessorMethod]
- public uint accel_key { get; set; }
- [NoAccessorMethod]
- public Gtk.CellRendererAccelMode accel_mode { get; set; }
- [NoAccessorMethod]
- public Gdk.ModifierType accel_mods { get; set; }
- [NoAccessorMethod]
- public uint keycode { get; set; }
- public virtual signal void accel_cleared (string path_string);
- public virtual signal void accel_edited (string path_string, uint accel_key, Gdk.ModifierType accel_mods, uint hardware_keycode);
- }
- [CCode (cheader_filename = "gtk/gtk.h", type_id = "gtk_cell_renderer_combo_get_type ()")]
- public class CellRendererCombo : Gtk.CellRendererText {
- [CCode (has_construct_function = false, type = "GtkCellRenderer*")]
- public CellRendererCombo ();
- [NoAccessorMethod]
- public bool has_entry { get; set; }
- [NoAccessorMethod]
- public Gtk.TreeModel model { owned get; set; }
- [NoAccessorMethod]
- public int text_column { get; set; }
- public virtual signal void changed (string p0, Gtk.TreeIter p1);
- }
- [CCode (cheader_filename = "gtk/gtk.h", type_id = "gtk_cell_renderer_pixbuf_get_type ()")]
- public class CellRendererPixbuf : Gtk.CellRenderer {
- [CCode (has_construct_function = false, type = "GtkCellRenderer*")]
- public CellRendererPixbuf ();
- [NoAccessorMethod]
- public bool follow_state { get; set; }
- [NoAccessorMethod]
- public GLib.Icon gicon { owned get; set; }
- [NoAccessorMethod]
- public string icon_name { owned get; set; }
- [NoAccessorMethod]
- public Gdk.Pixbuf pixbuf { owned get; set; }
- [NoAccessorMethod]
- public Gdk.Pixbuf pixbuf_expander_closed { owned get; set; }
- [NoAccessorMethod]
- public Gdk.Pixbuf pixbuf_expander_open { owned get; set; }
- [NoAccessorMethod]
- public string stock_detail { owned get; set; }
- [NoAccessorMethod]
- public string stock_id { owned get; set; }
- [NoAccessorMethod]
- public uint stock_size { get; set; }
- [NoAccessorMethod]
- public Cairo.Surface surface { owned get; set; }
- }
- [CCode (cheader_filename = "gtk/gtk.h", type_id = "gtk_cell_renderer_progress_get_type ()")]
- public class CellRendererProgress : Gtk.CellRenderer, Gtk.Orientable {
- [CCode (has_construct_function = false, type = "GtkCellRenderer*")]
- public CellRendererProgress ();
- [NoAccessorMethod]
- public bool inverted { get; set; }
- [NoAccessorMethod]
- public int pulse { get; set; }
- [NoAccessorMethod]
- public string text { owned get; set; }
- [NoAccessorMethod]
- public float text_xalign { get; set; }
- [NoAccessorMethod]
- public float text_yalign { get; set; }
- [NoAccessorMethod]
- public int value { get; set; }
- }
- [CCode (cheader_filename = "gtk/gtk.h", type_id = "gtk_cell_renderer_spin_get_type ()")]
- public class CellRendererSpin : Gtk.CellRendererText {
- [CCode (has_construct_function = false, type = "GtkCellRenderer*")]
- public CellRendererSpin ();
- [NoAccessorMethod]
- public Gtk.Adjustment adjustment { owned get; set; }
- [NoAccessorMethod]
- public double climb_rate { get; set; }
- [NoAccessorMethod]
- public uint digits { get; set; }
- }
- [CCode (cheader_filename = "gtk/gtk.h", type_id = "gtk_cell_renderer_spinner_get_type ()")]
- public class CellRendererSpinner : Gtk.CellRenderer {
- [CCode (has_construct_function = false, type = "GtkCellRenderer*")]
- public CellRendererSpinner ();
- [NoAccessorMethod]
- public bool active { get; set; }
- [NoAccessorMethod]
- public uint pulse { get; set; }
- [NoAccessorMethod]
- public Gtk.IconSize size { get; set; }
- }
- [CCode (cheader_filename = "gtk/gtk.h", type_id = "gtk_cell_renderer_text_get_type ()")]
- public class CellRendererText : Gtk.CellRenderer {
- [CCode (has_construct_function = false, type = "GtkCellRenderer*")]
- public CellRendererText ();
- public void set_fixed_height_from_font (int number_of_rows);
- [NoAccessorMethod]
- public bool align_set { get; set; }
- [NoAccessorMethod]
- public Pango.Alignment alignment { get; set; }
- [NoAccessorMethod]
- public Pango.AttrList attributes { owned get; set; }
- [NoAccessorMethod]
- public string background { set; }
- [Deprecated (replacement = "background_rgba", since = "3.4")]
- [NoAccessorMethod]
- public Gdk.Color background_gdk { get; set; }
- [NoAccessorMethod]
- public Gdk.RGBA background_rgba { get; set; }
- [NoAccessorMethod]
- public bool background_set { get; set; }
- [NoAccessorMethod]
- public bool editable { get; set; }
- [NoAccessorMethod]
- public bool editable_set { get; set; }
- [NoAccessorMethod]
- public Pango.EllipsizeMode ellipsize { get; set; }
- [NoAccessorMethod]
- public bool ellipsize_set { get; set; }
- [NoAccessorMethod]
- public string family { owned get; set; }
- [NoAccessorMethod]
- public bool family_set { get; set; }
- [NoAccessorMethod]
- public string font { owned get; set; }
- [NoAccessorMethod]
- public Pango.FontDescription font_desc { owned get; set; }
- [NoAccessorMethod]
- public string foreground { set; }
- [Deprecated (replacement = "foreground_rgba", since = "3.4")]
- [NoAccessorMethod]
- public Gdk.Color foreground_gdk { get; set; }
- [NoAccessorMethod]
- public Gdk.RGBA foreground_rgba { get; set; }
- [NoAccessorMethod]
- public bool foreground_set { get; set; }
- [NoAccessorMethod]
- public string language { owned get; set; }
- [NoAccessorMethod]
- public bool language_set { get; set; }
- [NoAccessorMethod]
- public string markup { set; }
- [NoAccessorMethod]
- public int max_width_chars { get; set; }
- [NoAccessorMethod]
- public string placeholder_text { owned get; set; }
- [NoAccessorMethod]
- public int rise { get; set; }
- [NoAccessorMethod]
- public bool rise_set { get; set; }
- [NoAccessorMethod]
- public double scale { get; set; }
- [NoAccessorMethod]
- public bool scale_set { get; set; }
- [NoAccessorMethod]
- public bool single_paragraph_mode { get; set; }
- [NoAccessorMethod]
- public int size { get; set; }
- [NoAccessorMethod]
- public double size_points { get; set; }
- [NoAccessorMethod]
- public bool size_set { get; set; }
- [NoAccessorMethod]
- public Pango.Stretch stretch { get; set; }
- [NoAccessorMethod]
- public bool stretch_set { get; set; }
- [NoAccessorMethod]
- public bool strikethrough { get; set; }
- [NoAccessorMethod]
- public bool strikethrough_set { get; set; }
- [NoAccessorMethod]
- public Pango.Style style { get; set; }
- [NoAccessorMethod]
- public bool style_set { get; set; }
- [NoAccessorMethod]
- public string text { owned get; set; }
- [NoAccessorMethod]
- public Pango.Underline underline { get; set; }
- [NoAccessorMethod]
- public bool underline_set { get; set; }
- [NoAccessorMethod]
- public Pango.Variant variant { get; set; }
- [NoAccessorMethod]
- public bool variant_set { get; set; }
- [NoAccessorMethod]
- public int weight { get; set; }
- [NoAccessorMethod]
- public bool weight_set { get; set; }
- [NoAccessorMethod]
- public int width_chars { get; set; }
- [NoAccessorMethod]
- public Pango.WrapMode wrap_mode { get; set; }
- [NoAccessorMethod]
- public int wrap_width { get; set; }
- public virtual signal void edited (string path, string new_text);
- }
- [CCode (cheader_filename = "gtk/gtk.h", type_id = "gtk_cell_renderer_toggle_get_type ()")]
- public class CellRendererToggle : Gtk.CellRenderer {
- [CCode (has_construct_function = false, type = "GtkCellRenderer*")]
- public CellRendererToggle ();
- public bool get_activatable ();
- public bool get_active ();
- public bool get_radio ();
- public void set_activatable (bool setting);
- public void set_active (bool setting);
- public void set_radio (bool radio);
- public bool activatable { get; set; }
- public bool active { get; set; }
- [NoAccessorMethod]
- public bool inconsistent { get; set; }
- [NoAccessorMethod]
- public int indicator_size { get; set; }
- public bool radio { get; set; }
- public virtual signal void toggled (string path);
- }
- [CCode (cheader_filename = "gtk/gtk.h", type_id = "gtk_cell_view_get_type ()")]
- public class CellView : Gtk.Widget, Atk.Implementor, Gtk.Buildable, Gtk.CellLayout, Gtk.Orientable {
- [CCode (has_construct_function = false, type = "GtkWidget*")]
- public CellView ();
- public Gtk.TreePath get_displayed_row ();
- public bool get_draw_sensitive ();
- public bool get_fit_model ();
- public unowned Gtk.TreeModel get_model ();
- public bool get_size_of_row (Gtk.TreePath path, out Gtk.Requisition requisition);
- [Deprecated (replacement = "set_background_rgba", since = "3.4")]
- public void set_background_color (Gdk.Color color);
- public void set_background_rgba (Gdk.RGBA rgba);
- public void set_displayed_row (Gtk.TreePath path);
- public void set_draw_sensitive (bool draw_sensitive);
- public void set_fit_model (bool fit_model);
- public void set_model (Gtk.TreeModel? model);
- [CCode (has_construct_function = false, type = "GtkWidget*")]
- public CellView.with_context (Gtk.CellArea area, Gtk.CellAreaContext context);
- [CCode (has_construct_function = false, type = "GtkWidget*")]
- public CellView.with_markup (string markup);
- [CCode (has_construct_function = false, type = "GtkWidget*")]
- public CellView.with_pixbuf (Gdk.Pixbuf pixbuf);
- [CCode (has_construct_function = false, type = "GtkWidget*")]
- public CellView.with_text (string text);
- [NoAccessorMethod]
- public string background { set; }
- [Deprecated (replacement = "background_rgba", since = "3.4")]
- [NoAccessorMethod]
- public Gdk.Color background_gdk { get; set; }
- [NoAccessorMethod]
- public Gdk.RGBA background_rgba { get; set; }
- [NoAccessorMethod]
- public bool background_set { get; set; }
- [NoAccessorMethod]
- public Gtk.CellArea cell_area { owned get; construct; }
- [NoAccessorMethod]
- public Gtk.CellAreaContext cell_area_context { owned get; construct; }
- public bool draw_sensitive { get; set; }
- public bool fit_model { get; set; }
- public Gtk.TreeModel model { get; set; }
- }
- [CCode (cheader_filename = "gtk/gtk.h", type_id = "gtk_check_button_get_type ()")]
- public class CheckButton : Gtk.ToggleButton, Atk.Implementor, Gtk.Buildable, Gtk.Actionable, Gtk.Activatable {
- [CCode (has_construct_function = false, type = "GtkWidget*")]
- public CheckButton ();
- [NoWrapper]
- public virtual void draw_indicator (Cairo.Context cr);
- [CCode (has_construct_function = false, type = "GtkWidget*")]
- public CheckButton.with_label (string label);
- [CCode (has_construct_function = false, type = "GtkWidget*")]
- public CheckButton.with_mnemonic (string label);
- }
- [CCode (cheader_filename = "gtk/gtk.h", type_id = "gtk_check_menu_item_get_type ()")]
- public class CheckMenuItem : Gtk.MenuItem, Atk.Implementor, Gtk.Buildable, Gtk.Activatable, Gtk.Actionable {
- [CCode (has_construct_function = false, type = "GtkWidget*")]
- public CheckMenuItem ();
- [NoWrapper]
- public virtual void draw_indicator (Cairo.Context cr);
- public bool get_active ();
- public bool get_draw_as_radio ();
- public bool get_inconsistent ();
- public void set_active (bool is_active);
- public void set_draw_as_radio (bool draw_as_radio);
- public void set_inconsistent (bool setting);
- [CCode (has_construct_function = false, type = "GtkWidget*")]
- public CheckMenuItem.with_label (string label);
- [CCode (has_construct_function = false, type = "GtkWidget*")]
- public CheckMenuItem.with_mnemonic (string label);
- public bool active { get; set; }
- public bool draw_as_radio { get; set; }
- public bool inconsistent { get; set; }
- [HasEmitter]
- public virtual signal void toggled ();
- }
- [CCode (cheader_filename = "gtk/gtk.h", type_id = "gtk_check_menu_item_accessible_get_type ()")]
- public class CheckMenuItemAccessible : Gtk.MenuItemAccessible, Atk.Component, Atk.Action, Atk.Selection {
- [CCode (has_construct_function = false)]
- protected CheckMenuItemAccessible ();
- }
- [CCode (cheader_filename = "gtk/gtk.h", type_id = "gtk_clipboard_get_type ()")]
- public class Clipboard : GLib.Object {
- [CCode (has_construct_function = false)]
- protected Clipboard ();
- public void clear ();
- public static unowned Gtk.Clipboard @get (Gdk.Atom selection);
- public unowned Gdk.Display get_display ();
- public static unowned Gtk.Clipboard get_for_display (Gdk.Display display, Gdk.Atom selection);
- public unowned GLib.Object get_owner ();
- public void request_contents (Gdk.Atom target, Gtk.ClipboardReceivedFunc callback);
- public void request_image (Gtk.ClipboardImageReceivedFunc callback);
- public void request_rich_text (Gtk.TextBuffer buffer, Gtk.ClipboardRichTextReceivedFunc callback);
- public void request_targets (Gtk.ClipboardTargetsReceivedFunc callback);
- public void request_text (Gtk.ClipboardTextReceivedFunc callback);
- public void request_uris (Gtk.ClipboardURIReceivedFunc callback);
- public void set_can_store (Gtk.TargetEntry[] targets);
- public void set_image (Gdk.Pixbuf pixbuf);
- public void set_text (string text, int len);
- public bool set_with_data (Gtk.TargetEntry[] targets, Gtk.ClipboardGetFunc get_func, Gtk.ClipboardClearFunc clear_func);
- public bool set_with_owner (Gtk.TargetEntry[] targets, Gtk.ClipboardGetFunc get_func, Gtk.ClipboardClearFunc clear_func, GLib.Object owner);
- public void store ();
- public Gtk.SelectionData? wait_for_contents (Gdk.Atom target);
- public Gdk.Pixbuf? wait_for_image ();
- [CCode (array_length_type = "gsize")]
- public uint8[]? wait_for_rich_text (Gtk.TextBuffer buffer, out Gdk.Atom format);
- public bool wait_for_targets (out Gdk.Atom[] targets);
- public string? wait_for_text ();
- [CCode (array_length = false, array_null_terminated = true)]
- public string[]? wait_for_uris ();
- public bool wait_is_image_available ();
- public bool wait_is_rich_text_available (Gtk.TextBuffer buffer);
- public bool wait_is_target_available (Gdk.Atom target);
- public bool wait_is_text_available ();
- public bool wait_is_uris_available ();
- public virtual signal void owner_change (Gdk.Event p0);
- }
- [CCode (cheader_filename = "gtk/gtk.h", type_id = "gtk_color_button_get_type ()")]
- public class ColorButton : Gtk.Button, Atk.Implementor, Gtk.Buildable, Gtk.Actionable, Gtk.Activatable, Gtk.ColorChooser {
- [CCode (has_construct_function = false, type = "GtkWidget*")]
- public ColorButton ();
- public uint16 get_alpha ();
- public void get_color (out Gdk.Color color);
- public unowned string get_title ();
- public bool get_use_alpha ();
- public void set_alpha (uint16 alpha);
- public void set_color (Gdk.Color color);
- public void set_title (string title);
- public void set_use_alpha (bool use_alpha);
- [CCode (has_construct_function = false, type = "GtkWidget*")]
- public ColorButton.with_color (Gdk.Color color);
- [CCode (has_construct_function = false, type = "GtkWidget*")]
- public ColorButton.with_rgba (Gdk.RGBA rgba);
- public uint alpha { get; set; }
- [Deprecated (replacement = "rgba", since = "3.4")]
- public Gdk.Color color { get; set; }
- public Gdk.RGBA rgba { get; set; }
- public string title { get; set; }
- public bool use_alpha { get; set; }
- public virtual signal void color_set ();
- }
- [CCode (cheader_filename = "gtk/gtk.h", type_id = "gtk_color_chooser_dialog_get_type ()")]
- public class ColorChooserDialog : Gtk.Dialog, Atk.Implementor, Gtk.Buildable, Gtk.ColorChooser {
- [CCode (has_construct_function = false, type = "GtkWidget*")]
- public ColorChooserDialog (string? title, Gtk.Window? parent);
- [NoAccessorMethod]
- public bool show_editor { get; set; }
- }
- [CCode (cheader_filename = "gtk/gtk.h", type_id = "gtk_color_chooser_widget_get_type ()")]
- public class ColorChooserWidget : Gtk.Box, Atk.Implementor, Gtk.Buildable, Gtk.Orientable, Gtk.ColorChooser {
- [CCode (has_construct_function = false, type = "GtkWidget*")]
- public ColorChooserWidget ();
- [NoAccessorMethod]
- public bool show_editor { get; set; }
- }
- [CCode (cheader_filename = "gtk/gtk.h", type_id = "gtk_color_selection_get_type ()")]
- public class ColorSelection : Gtk.Box, Atk.Implementor, Gtk.Buildable, Gtk.Orientable {
- [CCode (has_construct_function = false, type = "GtkWidget*")]
- public ColorSelection ();
- public uint16 get_current_alpha ();
- [Deprecated (replacement = "get_current_rgba", since = "3.4")]
- public void get_current_color (out Gdk.Color color);
- public Gdk.RGBA get_current_rgba ();
- public bool get_has_opacity_control ();
- public bool get_has_palette ();
- public uint16 get_previous_alpha ();
- public void get_previous_color (out Gdk.Color color);
- public Gdk.RGBA get_previous_rgba ();
- public bool is_adjusting ();
- public static bool palette_from_string (string str, out Gdk.Color[] colors);
- public static string palette_to_string (Gdk.Color[] colors);
- public static unowned Gtk.ColorSelectionChangePaletteWithScreenFunc set_change_palette_with_screen_hook (Gtk.ColorSelectionChangePaletteWithScreenFunc func);
- public void set_current_alpha (uint16 alpha);
- [Deprecated (replacement = "set_current_rgba", since = "3.4")]
- public void set_current_color (Gdk.Color color);
- public void set_current_rgba (Gdk.RGBA rgba);
- public void set_has_opacity_control (bool has_opacity);
- public void set_has_palette (bool has_palette);
- public void set_previous_alpha (uint16 alpha);
- public void set_previous_color (Gdk.Color color);
- public void set_previous_rgba (Gdk.RGBA rgba);
- public uint current_alpha { get; set; }
- [Deprecated (replacement = "current_rgba", since = "3.4")]
- public Gdk.Color current_color { get; set; }
- public Gdk.RGBA current_rgba { get; set; }
- public bool has_opacity_control { get; set; }
- public bool has_palette { get; set; }
- public virtual signal void color_changed ();
- }
- [CCode (cheader_filename = "gtk/gtk.h", type_id = "gtk_color_selection_dialog_get_type ()")]
- public class ColorSelectionDialog : Gtk.Dialog, Atk.Implementor, Gtk.Buildable {
- [CCode (has_construct_function = false, type = "GtkWidget*")]
- public ColorSelectionDialog (string title);
- public unowned Gtk.ColorSelection get_color_selection ();
- [NoAccessorMethod]
- public Gtk.Widget cancel_button { owned get; }
- public Gtk.Widget color_selection { get; }
- [NoAccessorMethod]
- public Gtk.Widget help_button { owned get; }
- [NoAccessorMethod]
- public Gtk.Widget ok_button { owned get; }
- }
- [CCode (cheader_filename = "gtk/gtk.h", type_id = "gtk_combo_box_get_type ()")]
- public class ComboBox : Gtk.Bin, Atk.Implementor, Gtk.Buildable, Gtk.CellLayout, Gtk.CellEditable {
- [CCode (has_construct_function = false, type = "GtkWidget*")]
- public ComboBox ();
- public int get_active ();
- public unowned string get_active_id ();
- public bool get_active_iter (out Gtk.TreeIter iter);
- public bool get_add_tearoffs ();
- public Gtk.SensitivityType get_button_sensitivity ();
- public int get_column_span_column ();
- public int get_entry_text_column ();
- public bool get_focus_on_click ();
- public bool get_has_entry ();
- public int get_id_column ();
- public unowned Gtk.TreeModel get_model ();
- public unowned Atk.Object get_popup_accessible ();
- public bool get_popup_fixed_width ();
- public unowned Gtk.TreeViewRowSeparatorFunc get_row_separator_func ();
- public int get_row_span_column ();
- public unowned string get_title ();
- public int get_wrap_width ();
- public void popup_for_device (Gdk.Device device);
- public void set_active (int index_);
- public bool set_active_id (string active_id);
- public void set_active_iter (Gtk.TreeIter? iter);
- public void set_add_tearoffs (bool add_tearoffs);
- public void set_button_sensitivity (Gtk.SensitivityType sensitivity);
- public void set_column_span_column (int column_span);
- public void set_entry_text_column (int text_column);
- public void set_focus_on_click (bool focus_on_click);
- public void set_id_column (int id_column);
- public void set_model (Gtk.TreeModel? model);
- public void set_popup_fixed_width (bool fixed);
- public void set_row_separator_func (owned Gtk.TreeViewRowSeparatorFunc func);
- public void set_row_span_column (int row_span);
- public void set_title (string title);
- public void set_wrap_width (int width);
- [CCode (has_construct_function = false, type = "GtkWidget*")]
- public ComboBox.with_area (Gtk.CellArea area);
- [CCode (has_construct_function = false, type = "GtkWidget*")]
- public ComboBox.with_area_and_entry (Gtk.CellArea area);
- [CCode (has_construct_function = false, type = "GtkWidget*")]
- public ComboBox.with_entry ();
- [CCode (has_construct_function = false, type = "GtkWidget*")]
- public ComboBox.with_model (Gtk.TreeModel model);
- [CCode (has_construct_function = false, type = "GtkWidget*")]
- public ComboBox.with_model_and_entry (Gtk.TreeModel model);
- public int active { get; set; }
- public string active_id { get; set; }
- public bool add_tearoffs { get; set; }
- public Gtk.SensitivityType button_sensitivity { get; set; }
- [NoAccessorMethod]
- public Gtk.CellArea cell_area { owned get; construct; }
- public int column_span_column { get; set; }
- public int entry_text_column { get; set; }
- public bool focus_on_click { get; set; }
- public bool has_entry { get; construct; }
- [NoAccessorMethod]
- public bool has_frame { get; set; }
- public int id_column { get; set; }
- public Gtk.TreeModel model { get; set; }
- public bool popup_fixed_width { get; set; }
- [NoAccessorMethod]
- public bool popup_shown { get; }
- public int row_span_column { get; set; }
- [NoAccessorMethod]
- public string tearoff_title { owned get; set; }
- public int wrap_width { get; set; }
- public virtual signal void changed ();
- public virtual signal string format_entry_text (string path);
- public virtual signal void move_active (Gtk.ScrollType p0);
- [HasEmitter]
- public virtual signal bool popdown ();
- [HasEmitter]
- public virtual signal void popup ();
- }
- [CCode (cheader_filename = "gtk/gtk.h", type_id = "gtk_combo_box_accessible_get_type ()")]
- public class ComboBoxAccessible : Gtk.ContainerAccessible, Atk.Component, Atk.Action, Atk.Selection {
- [CCode (has_construct_function = false)]
- protected ComboBoxAccessible ();
- }
- [CCode (cheader_filename = "gtk/gtk.h", type_id = "gtk_combo_box_text_get_type ()")]
- public class ComboBoxText : Gtk.ComboBox, Atk.Implementor, Gtk.Buildable, Gtk.CellLayout, Gtk.CellEditable {
- [CCode (has_construct_function = false, type = "GtkWidget*")]
- public ComboBoxText ();
- public void append (string id, string text);
- public void append_text (string text);
- public string get_active_text ();
- public void insert (int position, string id, string text);
- public void insert_text (int position, string text);
- public void prepend (string id, string text);
- public void prepend_text (string text);
- public void remove (int position);
- public void remove_all ();
- [CCode (has_construct_function = false, type = "GtkWidget*")]
- public ComboBoxText.with_entry ();
- }
- [CCode (cheader_filename = "gtk/gtk.h", type_id = "gtk_container_get_type ()")]
- public abstract class Container : Gtk.Widget, Atk.Implementor, Gtk.Buildable {
- [CCode (has_construct_function = false)]
- protected Container ();
- public void add_with_properties (Gtk.Widget widget, ...);
- public void child_get (Gtk.Widget child, ...);
- public void child_get_property (Gtk.Widget child, string property_name, GLib.Value value);
- public void child_get_valist (Gtk.Widget child, string first_property_name, va_list var_args);
- public void child_notify (Gtk.Widget child, string child_property);
- public void child_set (Gtk.Widget child, ...);
- public void child_set_property (Gtk.Widget child, string property_name, GLib.Value value);
- public void child_set_valist (Gtk.Widget child, string first_property_name, va_list var_args);
- public virtual GLib.Type child_type ();
- public static unowned GLib.ParamSpec class_find_child_property (GLib.ObjectClass cclass, string property_name);
- public static unowned GLib.ParamSpec class_list_child_properties (GLib.ObjectClass cclass, uint n_properties);
- [NoWrapper]
- public virtual unowned string composite_name (Gtk.Widget child);
- public void forall (Gtk.Callback callback);
- [CCode (vfunc_name = "forall")]
- [NoWrapper]
- public virtual void forall_internal (bool include_internal, Gtk.Callback callback);
- public void @foreach (Gtk.Callback callback);
- public uint get_border_width ();
- [NoWrapper]
- public virtual void get_child_property (Gtk.Widget child, uint property_id, GLib.Value value, GLib.ParamSpec pspec);
- public GLib.List get_children ();
- public bool get_focus_chain (out GLib.List focusable_widgets);
- public unowned Gtk.Widget get_focus_child ();
- public unowned Gtk.Adjustment get_focus_hadjustment ();
- public unowned Gtk.Adjustment get_focus_vadjustment ();
- public virtual Gtk.WidgetPath get_path_for_child (Gtk.Widget child);
- public Gtk.ResizeMode get_resize_mode ();
- [CCode (cname = "gtk_container_class_handle_border_width")]
- public class void handle_border_width ();
- [CCode (cname = "gtk_container_class_install_child_property")]
- public class void install_child_property (uint property_id, GLib.ParamSpec pspec);
- public void propagate_draw (Gtk.Widget child, Cairo.Context cr);
- public void resize_children ();
- public void set_border_width (uint border_width);
- [NoWrapper]
- public virtual void set_child_property (Gtk.Widget child, uint property_id, GLib.Value value, GLib.ParamSpec pspec);
- public void set_focus_chain (GLib.List focusable_widgets);
- public void set_focus_hadjustment (Gtk.Adjustment adjustment);
- public void set_focus_vadjustment (Gtk.Adjustment adjustment);
- public void set_reallocate_redraws (bool needs_redraws);
- public void set_resize_mode (Gtk.ResizeMode resize_mode);
- public void unset_focus_chain ();
- public uint border_width { get; set; }
- [NoAccessorMethod]
- public Gtk.Widget child { set; }
- public Gtk.ResizeMode resize_mode { get; set; }
- [HasEmitter]
- public virtual signal void add (Gtk.Widget widget);
- [HasEmitter]
- public virtual signal void check_resize ();
- [HasEmitter]
- public virtual signal void remove (Gtk.Widget widget);
- [HasEmitter]
- public virtual signal void set_focus_child (Gtk.Widget? child);
- }
- [CCode (cheader_filename = "gtk/gtk.h", type_id = "gtk_container_accessible_get_type ()")]
- public class ContainerAccessible : Gtk.WidgetAccessible, Atk.Component {
- [CCode (has_construct_function = false)]
- protected ContainerAccessible ();
- [NoWrapper]
- public virtual int add_gtk (Gtk.Container container, Gtk.Widget widget, void* data);
- [NoWrapper]
- public virtual int remove_gtk (Gtk.Container container, Gtk.Widget widget, void* data);
- }
- [CCode (cheader_filename = "gtk/gtk.h", type_id = "gtk_container_cell_accessible_get_type ()")]
- public class ContainerCellAccessible : Gtk.CellAccessible, Atk.Action, Atk.Component {
- [CCode (has_construct_function = false)]
- public ContainerCellAccessible ();
- public void add_child (Gtk.CellAccessible child);
- public unowned GLib.List get_children ();
- public void remove_child (Gtk.CellAccessible child);
- }
- [CCode (cheader_filename = "gtk/gtk.h")]
- public class CssProvider : GLib.Object, Gtk.StyleProvider {
- [CCode (has_construct_function = false)]
- public CssProvider ();
- public static GLib.Quark error_quark ();
- public static unowned Gtk.CssProvider get_default ();
- public static unowned Gtk.CssProvider get_named (string name, string? variant);
- public bool load_from_data (string data, ssize_t length) throws GLib.Error;
- public bool load_from_file (GLib.File file) throws GLib.Error;
- public bool load_from_path (string path) throws GLib.Error;
- public string to_string ();
- public virtual signal void parsing_error (Gtk.CssSection section, GLib.Error error);
- }
- [CCode (cheader_filename = "gtk/gtk.h", ref_function = "gtk_css_section_ref", type_id = "gtk_css_section_get_type ()", unref_function = "gtk_css_section_unref")]
- [Compact]
- public class CssSection {
- public uint get_end_line ();
- public uint get_end_position ();
- public unowned GLib.File get_file ();
- public unowned Gtk.CssSection get_parent ();
- public Gtk.CssSectionType get_section_type ();
- public uint get_start_line ();
- public uint get_start_position ();
- }
- [CCode (cheader_filename = "gtk/gtk.h", type_id = "gtk_dialog_get_type ()")]
- public class Dialog : Gtk.Window, Atk.Implementor, Gtk.Buildable {
- [CCode (has_construct_function = false, type = "GtkWidget*")]
- public Dialog ();
- public void add_action_widget (Gtk.Widget child, int response_id);
- public unowned Gtk.Widget add_button (string button_text, int response_id);
- public void add_buttons (...);
- public unowned Gtk.Widget get_action_area ();
- [CCode (type = "GtkWidget*")]
- public unowned Gtk.Box get_content_area ();
- public unowned Gtk.Widget get_header_bar ();
- public int get_response_for_widget (Gtk.Widget widget);
- public unowned Gtk.Widget get_widget_for_response (int response_id);
- public int run ();
- [CCode (sentinel = "-1")]
- public void set_alternative_button_order (...);
- public void set_alternative_button_order_from_array ([CCode (array_length_pos = 0.5)] int[] new_order);
- public void set_default_response (int response_id);
- public void set_response_sensitive (int response_id, bool setting);
- [CCode (has_construct_function = false, type = "GtkWidget*")]
- public Dialog.with_buttons (string? title, Gtk.Window? parent, Gtk.DialogFlags flags, ...);
- [NoAccessorMethod]
- public int use_header_bar { get; construct; }
- public virtual signal void close ();
- [HasEmitter]
- public virtual signal void response (int response_id);
- }
- [CCode (cheader_filename = "gtk/gtk.h", type_id = "gtk_drawing_area_get_type ()")]
- public class DrawingArea : Gtk.Widget, Atk.Implementor, Gtk.Buildable {
- [CCode (has_construct_function = false, type = "GtkWidget*")]
- public DrawingArea ();
- }
- [CCode (cheader_filename = "gtk/gtk.h", type_id = "gtk_entry_get_type ()")]
- public class Entry : Gtk.Widget, Atk.Implementor, Gtk.Buildable, Gtk.Editable, Gtk.CellEditable {
- [CCode (has_construct_function = false, type = "GtkWidget*")]
- public Entry ();
- public bool get_activates_default ();
- public float get_alignment ();
- public unowned Pango.AttrList get_attributes ();
- public unowned Gtk.EntryBuffer get_buffer ();
- public unowned Gtk.EntryCompletion get_completion ();
- public int get_current_icon_drag_source ();
- public unowned Gtk.Adjustment get_cursor_hadjustment ();
- [NoWrapper]
- public virtual void get_frame_size (int x, int y, int width, int height);
- public bool get_has_frame ();
- public bool get_icon_activatable (Gtk.EntryIconPosition icon_pos);
- public Gdk.Rectangle get_icon_area (Gtk.EntryIconPosition icon_pos);
- public int get_icon_at_pos (int x, int y);
- public unowned GLib.Icon get_icon_gicon (Gtk.EntryIconPosition icon_pos);
- public unowned string get_icon_name (Gtk.EntryIconPosition icon_pos);
- public unowned Gdk.Pixbuf get_icon_pixbuf (Gtk.EntryIconPosition icon_pos);
- public bool get_icon_sensitive (Gtk.EntryIconPosition icon_pos);
- public unowned string get_icon_stock (Gtk.EntryIconPosition icon_pos);
- public Gtk.ImageType get_icon_storage_type (Gtk.EntryIconPosition icon_pos);
- public string? get_icon_tooltip_markup (Gtk.EntryIconPosition icon_pos);
- public string? get_icon_tooltip_text (Gtk.EntryIconPosition icon_pos);
- public unowned Gtk.Border? get_inner_border ();
- public Gtk.InputHints get_input_hints ();
- public Gtk.InputPurpose get_input_purpose ();
- public unichar get_invisible_char ();
- public unowned Pango.Layout get_layout ();
- public void get_layout_offsets (out int x, out int y);
- public int get_max_length ();
- public int get_max_width_chars ();
- public bool get_overwrite_mode ();
- public unowned string get_placeholder_text ();
- public double get_progress_fraction ();
- public double get_progress_pulse_step ();
- public unowned Pango.TabArray? get_tabs ();
- public unowned string get_text ();
- public void get_text_area (out Gdk.Rectangle text_area);
- [NoWrapper]
- public virtual void get_text_area_size (out int x, out int y, out int width, out int height);
- public uint16 get_text_length ();
- public bool get_visibility ();
- public int get_width_chars ();
- public bool im_context_filter_keypress (Gdk.EventKey event);
- public int layout_index_to_text_index (int layout_index);
- public void progress_pulse ();
- public void reset_im_context ();
- public void set_activates_default (bool setting);
- public void set_alignment (float xalign);
- public void set_attributes (Pango.AttrList attrs);
- public void set_buffer (Gtk.EntryBuffer buffer);
- public void set_completion (Gtk.EntryCompletion completion);
- public void set_cursor_hadjustment (Gtk.Adjustment adjustment);
- public void set_has_frame (bool setting);
- public void set_icon_activatable (Gtk.EntryIconPosition icon_pos, bool activatable);
- public void set_icon_drag_source (Gtk.EntryIconPosition icon_pos, Gtk.TargetList target_list, Gdk.DragAction actions);
- public void set_icon_from_gicon (Gtk.EntryIconPosition icon_pos, GLib.Icon? icon);
- public void set_icon_from_icon_name (Gtk.EntryIconPosition icon_pos, string? icon_name);
- public void set_icon_from_pixbuf (Gtk.EntryIconPosition icon_pos, Gdk.Pixbuf? pixbuf);
- public void set_icon_from_stock (Gtk.EntryIconPosition icon_pos, string? stock_id);
- public void set_icon_sensitive (Gtk.EntryIconPosition icon_pos, bool sensitive);
- public void set_icon_tooltip_markup (Gtk.EntryIconPosition icon_pos, string? tooltip);
- public void set_icon_tooltip_text (Gtk.EntryIconPosition icon_pos, string? tooltip);
- [Deprecated (since = "3.4")]
- public void set_inner_border (Gtk.Border border);
- public void set_input_hints (Gtk.InputHints hints);
- public void set_input_purpose (Gtk.InputPurpose purpose);
- public void set_invisible_char (unichar ch);
- public void set_max_length (int max);
- public void set_max_width_chars (int n_chars);
- public void set_overwrite_mode (bool overwrite);
- public void set_placeholder_text (string text);
- public void set_progress_fraction (double fraction);
- public void set_progress_pulse_step (double fraction);
- public void set_tabs (Pango.TabArray tabs);
- public void set_text (string text);
- public void set_visibility (bool visible);
- public void set_width_chars (int n_chars);
- public int text_index_to_layout_index (int text_index);
- public void unset_invisible_char ();
- [CCode (has_construct_function = false, type = "GtkWidget*")]
- public Entry.with_buffer (Gtk.EntryBuffer buffer);
- public bool activates_default { get; set; }
- public Pango.AttrList attributes { get; set; }
- public Gtk.EntryBuffer buffer { get; set construct; }
- [NoAccessorMethod]
- public bool caps_lock_warning { get; set; }
- public Gtk.EntryCompletion completion { get; set; }
- [NoAccessorMethod]
- public int cursor_position { get; }
- [NoAccessorMethod]
- public bool editable { get; set; }
- public bool has_frame { get; set; }
- [NoAccessorMethod]
- public string im_module { owned get; set; }
- [Deprecated (since = "3.4")]
- public Gtk.Border inner_border { get; set; }
- public Gtk.InputHints input_hints { get; set; }
- public Gtk.InputPurpose input_purpose { get; set; }
- public uint invisible_char { get; set; }
- [NoAccessorMethod]
- public bool invisible_char_set { get; set; }
- public int max_length { get; set; }
- public int max_width_chars { get; set; }
- public bool overwrite_mode { get; set; }
- public string placeholder_text { get; set; }
- [NoAccessorMethod]
- public bool populate_all { get; set; }
- [NoAccessorMethod]
- public bool primary_icon_activatable { get; set; }
- [NoAccessorMethod]
- public GLib.Icon primary_icon_gicon { owned get; set; }
- [NoAccessorMethod]
- public string primary_icon_name { owned get; set; }
- [NoAccessorMethod]
- public Gdk.Pixbuf primary_icon_pixbuf { owned get; set; }
- [NoAccessorMethod]
- public bool primary_icon_sensitive { get; set; }
- [NoAccessorMethod]
- public string primary_icon_stock { owned get; set; }
- [NoAccessorMethod]
- public Gtk.ImageType primary_icon_storage_type { get; }
- [NoAccessorMethod]
- public string primary_icon_tooltip_markup { owned get; set; }
- [NoAccessorMethod]
- public string primary_icon_tooltip_text { owned get; set; }
- public double progress_fraction { get; set; }
- public double progress_pulse_step { get; set; }
- [NoAccessorMethod]
- public int scroll_offset { get; }
- [NoAccessorMethod]
- public bool secondary_icon_activatable { get; set; }
- [NoAccessorMethod]
- public GLib.Icon secondary_icon_gicon { owned get; set; }
- [NoAccessorMethod]
- public string secondary_icon_name { owned get; set; }
- [NoAccessorMethod]
- public Gdk.Pixbuf secondary_icon_pixbuf { owned get; set; }
- [NoAccessorMethod]
- public bool secondary_icon_sensitive { get; set; }
- [NoAccessorMethod]
- public string secondary_icon_stock { owned get; set; }
- [NoAccessorMethod]
- public Gtk.ImageType secondary_icon_storage_type { get; }
- [NoAccessorMethod]
- public string secondary_icon_tooltip_markup { owned get; set; }
- [NoAccessorMethod]
- public string secondary_icon_tooltip_text { owned get; set; }
- [NoAccessorMethod]
- public int selection_bound { get; }
- [NoAccessorMethod]
- public Gtk.ShadowType shadow_type { get; set; }
- public Pango.TabArray tabs { get; set; }
- public string text { get; set; }
- public uint text_length { get; }
- [NoAccessorMethod]
- public bool truncate_multiline { get; set; }
- public bool visibility { get; set; }
- public int width_chars { get; set; }
- [NoAccessorMethod]
- public float xalign { get; set; }
- public virtual signal void activate ();
- public virtual signal void backspace ();
- public virtual signal void copy_clipboard ();
- public virtual signal void cut_clipboard ();
- public virtual signal void delete_from_cursor (Gtk.DeleteType type, int count);
- public virtual signal void icon_press (Gtk.EntryIconPosition p0, Gdk.Event p1);
- public virtual signal void icon_release (Gtk.EntryIconPosition p0, Gdk.Event p1);
- public virtual signal void insert_at_cursor (string str);
- public virtual signal void move_cursor (Gtk.MovementStep step, int count, bool extend_selection);
- public virtual signal void paste_clipboard ();
- public virtual signal void populate_popup (Gtk.Menu popup);
- public virtual signal void preedit_changed (string p0);
- public virtual signal void toggle_overwrite ();
- }
- [CCode (cheader_filename = "gtk/gtk.h", type_id = "gtk_entry_accessible_get_type ()")]
- public class EntryAccessible : Gtk.WidgetAccessible, Atk.Component, Atk.EditableText, Atk.Text, Atk.Action {
- [CCode (has_construct_function = false)]
- protected EntryAccessible ();
- }
- [CCode (cheader_filename = "gtk/gtk.h", type_id = "gtk_entry_buffer_get_type ()")]
- public class EntryBuffer : GLib.Object {
- [CCode (has_construct_function = false)]
- public EntryBuffer (uint8[] initial_chars);
- public virtual uint delete_text (uint position, int n_chars);
- public void emit_deleted_text (uint position, uint n_chars);
- public void emit_inserted_text (uint position, uint8[] chars);
- public size_t get_bytes ();
- public virtual uint get_length ();
- public int get_max_length ();
- public virtual unowned string get_text ();
- public virtual uint insert_text (uint position, uint8[] chars);
- public void set_max_length (int max_length);
- public void set_text (uint8[] chars);
- public uint length { get; }
- public int max_length { get; set; }
- public string text { get; set; }
- public virtual signal void deleted_text (uint position, uint n_chars);
- public virtual signal void inserted_text (uint position, string chars, uint n_chars);
- }
- [CCode (cheader_filename = "gtk/gtk.h", type_id = "gtk_entry_completion_get_type ()")]
- public class EntryCompletion : GLib.Object, Gtk.CellLayout, Gtk.Buildable {
- [CCode (has_construct_function = false)]
- public EntryCompletion ();
- public void complete ();
- public string compute_prefix (string key);
- public void delete_action (int index_);
- public unowned string get_completion_prefix ();
- public unowned Gtk.Widget get_entry ();
- public bool get_inline_completion ();
- public bool get_inline_selection ();
- public int get_minimum_key_length ();
- public unowned Gtk.TreeModel get_model ();
- public bool get_popup_completion ();
- public bool get_popup_set_width ();
- public bool get_popup_single_match ();
- public int get_text_column ();
- public void insert_action_markup (int index_, string markup);
- public void insert_action_text (int index_, string text);
- public void set_inline_completion (bool inline_completion);
- public void set_inline_selection (bool inline_selection);
- public void set_match_func (owned Gtk.EntryCompletionMatchFunc func);
- public void set_minimum_key_length (int length);
- public void set_model (Gtk.TreeModel? model);
- public void set_popup_completion (bool popup_completion);
- public void set_popup_set_width (bool popup_set_width);
- public void set_popup_single_match (bool popup_single_match);
- public void set_text_column (int column);
- [CCode (has_construct_function = false)]
- public EntryCompletion.with_area (Gtk.CellArea area);
- [NoAccessorMethod]
- public Gtk.CellArea cell_area { owned get; construct; }
- public bool inline_completion { get; set; }
- public bool inline_selection { get; set; }
- public int minimum_key_length { get; set; }
- public Gtk.TreeModel model { get; set; }
- public bool popup_completion { get; set; }
- public bool popup_set_width { get; set; }
- public bool popup_single_match { get; set; }
- public int text_column { get; set; }
- public virtual signal void action_activated (int index_);
- public virtual signal bool cursor_on_match (Gtk.TreeModel model, Gtk.TreeIter iter);
- [HasEmitter]
- public virtual signal bool insert_prefix (string prefix);
- public virtual signal bool match_selected (Gtk.TreeModel model, Gtk.TreeIter iter);
- public virtual signal void no_matches ();
- }
- [CCode (cheader_filename = "gtk/gtk.h", type_id = "gtk_entry_icon_accessible_get_type ()")]
- public class EntryIconAccessible : Atk.Object, Atk.Action, Atk.Component {
- [CCode (has_construct_function = false)]
- protected EntryIconAccessible ();
- }
- [CCode (cheader_filename = "gtk/gtk.h", type_id = "gtk_event_box_get_type ()")]
- public class EventBox : Gtk.Bin, Atk.Implementor, Gtk.Buildable {
- [CCode (has_construct_function = false, type = "GtkWidget*")]
- public EventBox ();
- public bool get_above_child ();
- public bool get_visible_window ();
- public void set_above_child (bool above_child);
- public void set_visible_window (bool visible_window);
- public bool above_child { get; set; }
- public bool visible_window { get; set; }
- }
- [CCode (cheader_filename = "gtk/gtk.h", type_id = "gtk_event_controller_get_type ()")]
- public abstract class EventController : GLib.Object {
- [CCode (has_construct_function = false)]
- protected EventController ();
- public Gtk.PropagationPhase get_propagation_phase ();
- public unowned Gtk.Widget get_widget ();
- public bool handle_event (Gdk.Event event);
- public void reset ();
- public void set_propagation_phase (Gtk.PropagationPhase phase);
- public Gtk.PropagationPhase propagation_phase { get; set; }
- public Gtk.Widget widget { get; construct; }
- }
- [CCode (cheader_filename = "gtk/gtk.h", type_id = "gtk_expander_get_type ()")]
- public class Expander : Gtk.Bin, Atk.Implementor, Gtk.Buildable {
- [CCode (has_construct_function = false, type = "GtkWidget*")]
- public Expander (string label);
- public bool get_expanded ();
- public unowned string get_label ();
- public bool get_label_fill ();
- public unowned Gtk.Widget get_label_widget ();
- public bool get_resize_toplevel ();
- public int get_spacing ();
- public bool get_use_markup ();
- public bool get_use_underline ();
- public void set_expanded (bool expanded);
- public void set_label (string label);
- public void set_label_fill (bool label_fill);
- public void set_label_widget (Gtk.Widget label_widget);
- public void set_resize_toplevel (bool resize_toplevel);
- public void set_spacing (int spacing);
- public void set_use_markup (bool use_markup);
- public void set_use_underline (bool use_underline);
- [CCode (has_construct_function = false, type = "GtkWidget*")]
- public Expander.with_mnemonic (string label);
- public bool expanded { get; set construct; }
- public string label { get; set construct; }
- public bool label_fill { get; set construct; }
- public Gtk.Widget label_widget { get; set; }
- public bool resize_toplevel { get; set; }
- public int spacing { get; set; }
- public bool use_markup { get; set construct; }
- public bool use_underline { get; set construct; }
- public virtual signal void activate ();
- }
- [CCode (cheader_filename = "gtk/gtk.h", type_id = "gtk_expander_accessible_get_type ()")]
- public class ExpanderAccessible : Gtk.ContainerAccessible, Atk.Component, Atk.Action {
- [CCode (has_construct_function = false)]
- protected ExpanderAccessible ();
- }
- [CCode (cheader_filename = "gtk/gtk.h", type_id = "gtk_file_chooser_button_get_type ()")]
- public class FileChooserButton : Gtk.Box, Atk.Implementor, Gtk.Buildable, Gtk.Orientable, Gtk.FileChooser {
- [CCode (has_construct_function = false, type = "GtkWidget*")]
- public FileChooserButton (string title, Gtk.FileChooserAction action);
- public bool get_focus_on_click ();
- public unowned string get_title ();
- public int get_width_chars ();
- public void set_focus_on_click (bool focus_on_click);
- public void set_title (string title);
- public void set_width_chars (int n_chars);
- [CCode (has_construct_function = false, type = "GtkWidget*")]
- public FileChooserButton.with_dialog (Gtk.Dialog dialog);
- public Gtk.FileChooser dialog { construct; }
- public bool focus_on_click { get; set; }
- public string title { get; set; }
- public int width_chars { get; set; }
- public virtual signal void file_set ();
- }
- [CCode (cheader_filename = "gtk/gtk.h", type_id = "gtk_file_chooser_dialog_get_type ()")]
- public class FileChooserDialog : Gtk.Dialog, Atk.Implementor, Gtk.Buildable, Gtk.FileChooser {
- [CCode (has_construct_function = false, type = "GtkWidget*")]
- public FileChooserDialog (string? title, Gtk.Window? parent, Gtk.FileChooserAction action, ...);
- }
- [CCode (cheader_filename = "gtk/gtk.h", type_id = "gtk_file_chooser_widget_get_type ()")]
- public class FileChooserWidget : Gtk.Box, Atk.Implementor, Gtk.Buildable, Gtk.Orientable, Gtk.FileChooser, Gtk.FileChooserEmbed {
- [CCode (has_construct_function = false, type = "GtkWidget*")]
- public FileChooserWidget (Gtk.FileChooserAction action);
- public virtual signal void desktop_folder ();
- public virtual signal void down_folder ();
- public virtual signal void home_folder ();
- public virtual signal void location_popup (string p0);
- public virtual signal void location_popup_on_paste ();
- public virtual signal void location_toggle_popup ();
- public virtual signal void quick_bookmark (int p0);
- public virtual signal void recent_shortcut ();
- public virtual signal void search_shortcut ();
- public virtual signal void show_hidden ();
- public virtual signal void up_folder ();
- }
- [CCode (cheader_filename = "gtk/gtk.h", type_id = "gtk_file_filter_get_type ()")]
- public class FileFilter : GLib.InitiallyUnowned, Gtk.Buildable {
- [CCode (has_construct_function = false)]
- public FileFilter ();
- public void add_custom (Gtk.FileFilterFlags needed, owned Gtk.FileFilterFunc func);
- public void add_mime_type (string mime_type);
- public void add_pattern (string pattern);
- public void add_pixbuf_formats ();
- public bool filter (Gtk.FileFilterInfo filter_info);
- [CCode (cname = "gtk_file_filter_get_name")]
- public unowned string get_filter_name ();
- public Gtk.FileFilterFlags get_needed ();
- [CCode (cname = "gtk_file_filter_set_name")]
- public void set_filter_name (string name);
- }
- [CCode (cheader_filename = "gtk/gtk.h")]
- [Compact]
- public class FileFilterInfo {
- public Gtk.FileFilterFlags contains;
- public weak string display_name;
- public weak string filename;
- public weak string mime_type;
- public weak string uri;
- }
- [CCode (cheader_filename = "gtk/gtk.h", type_id = "gtk_fixed_get_type ()")]
- public class Fixed : Gtk.Container, Atk.Implementor, Gtk.Buildable {
- [CCode (has_construct_function = false, type = "GtkWidget*")]
- public Fixed ();
- public void move (Gtk.Widget widget, int x, int y);
- public void put (Gtk.Widget widget, int x, int y);
- }
- [CCode (cheader_filename = "gtk/gtk.h")]
- [Compact]
- public class FixedChild {
- public weak Gtk.Widget widget;
- public int x;
- public int y;
- }
- [CCode (cheader_filename = "gtk/gtk.h", type_id = "gtk_flow_box_get_type ()")]
- public class FlowBox : Gtk.Container, Atk.Implementor, Gtk.Buildable, Gtk.Orientable {
- [CCode (has_construct_function = false, type = "GtkWidget*")]
- public FlowBox ();
- public bool get_activate_on_single_click ();
- public unowned Gtk.FlowBoxChild get_child_at_index (int idx);
- public uint get_column_spacing ();
- public bool get_homogeneous ();
- public uint get_max_children_per_line ();
- public uint get_min_children_per_line ();
- public uint get_row_spacing ();
- public GLib.List get_selected_children ();
- public Gtk.SelectionMode get_selection_mode ();
- public void insert (Gtk.Widget widget, int position);
- public void invalidate_filter ();
- public void invalidate_sort ();
- public void select_child (Gtk.FlowBoxChild child);
- public void selected_foreach (Gtk.FlowBoxForeachFunc func);
- public void set_activate_on_single_click (bool single);
- public void set_column_spacing (uint spacing);
- public void set_filter_func (owned Gtk.FlowBoxFilterFunc? filter_func);
- public void set_hadjustment (Gtk.Adjustment adjustment);
- public void set_homogeneous (bool homogeneous);
- public void set_max_children_per_line (uint n_children);
- public void set_min_children_per_line (uint n_children);
- public void set_row_spacing (uint spacing);
- public void set_selection_mode (Gtk.SelectionMode mode);
- public void set_sort_func (owned Gtk.FlowBoxSortFunc? sort_func);
- public void set_vadjustment (Gtk.Adjustment adjustment);
- public void unselect_child (Gtk.FlowBoxChild child);
- public bool activate_on_single_click { get; set; }
- public uint column_spacing { get; set; }
- public bool homogeneous { get; set; }
- public uint max_children_per_line { get; set; }
- public uint min_children_per_line { get; set; }
- public uint row_spacing { get; set; }
- public Gtk.SelectionMode selection_mode { get; set; }
- public virtual signal void activate_cursor_child ();
- public virtual signal void child_activated (Gtk.FlowBoxChild child);
- public virtual signal void move_cursor (Gtk.MovementStep step, int count);
- [HasEmitter]
- public virtual signal void select_all ();
- public virtual signal void selected_children_changed ();
- public virtual signal void toggle_cursor_child ();
- [HasEmitter]
- public virtual signal void unselect_all ();
- }
- [CCode (cheader_filename = "gtk/gtk.h", type_id = "gtk_flow_box_accessible_get_type ()")]
- public class FlowBoxAccessible : Gtk.ContainerAccessible, Atk.Component, Atk.Selection {
- [CCode (has_construct_function = false)]
- protected FlowBoxAccessible ();
- }
- [CCode (cheader_filename = "gtk/gtk.h", type_id = "gtk_flow_box_child_get_type ()")]
- public class FlowBoxChild : Gtk.Bin, Atk.Implementor, Gtk.Buildable {
- [CCode (has_construct_function = false, type = "GtkWidget*")]
- public FlowBoxChild ();
- public void changed ();
- public int get_index ();
- public bool is_selected ();
- public virtual signal void activate ();
- }
- [CCode (cheader_filename = "gtk/gtk.h", type_id = "gtk_flow_box_child_accessible_get_type ()")]
- public class FlowBoxChildAccessible : Gtk.ContainerAccessible, Atk.Component {
- [CCode (has_construct_function = false)]
- protected FlowBoxChildAccessible ();
- }
- [CCode (cheader_filename = "gtk/gtk.h", type_id = "gtk_font_button_get_type ()")]
- public class FontButton : Gtk.Button, Atk.Implementor, Gtk.Buildable, Gtk.Actionable, Gtk.Activatable, Gtk.FontChooser {
- [CCode (has_construct_function = false, type = "GtkWidget*")]
- public FontButton ();
- public unowned string get_font_name ();
- public bool get_show_size ();
- public bool get_show_style ();
- public unowned string get_title ();
- public bool get_use_font ();
- public bool get_use_size ();
- public bool set_font_name (string fontname);
- public void set_show_size (bool show_size);
- public void set_show_style (bool show_style);
- public void set_title (string title);
- public void set_use_font (bool use_font);
- public void set_use_size (bool use_size);
- [CCode (has_construct_function = false, type = "GtkWidget*")]
- public FontButton.with_font (string fontname);
- public string font_name { get; set; }
- public bool show_size { get; set; }
- public bool show_style { get; set; }
- public string title { get; set; }
- public bool use_font { get; set; }
- public bool use_size { get; set; }
- public virtual signal void font_set ();
- }
- [CCode (cheader_filename = "gtk/gtk.h", type_id = "gtk_font_chooser_dialog_get_type ()")]
- public class FontChooserDialog : Gtk.Dialog, Atk.Implementor, Gtk.Buildable, Gtk.FontChooser {
- [CCode (has_construct_function = false, type = "GtkWidget*")]
- public FontChooserDialog (string? title, Gtk.Window? parent);
- }
- [CCode (cheader_filename = "gtk/gtk.h", type_id = "gtk_font_chooser_widget_get_type ()")]
- public class FontChooserWidget : Gtk.Box, Atk.Implementor, Gtk.Buildable, Gtk.Orientable, Gtk.FontChooser {
- [CCode (has_construct_function = false, type = "GtkWidget*")]
- public FontChooserWidget ();
- }
- [CCode (cheader_filename = "gtk/gtk.h", type_id = "gtk_font_selection_get_type ()")]
- public class FontSelection : Gtk.Box, Atk.Implementor, Gtk.Buildable, Gtk.Orientable {
- [CCode (has_construct_function = false, type = "GtkWidget*")]
- public FontSelection ();
- public unowned Pango.FontFace get_face ();
- public unowned Gtk.Widget get_face_list ();
- public unowned Pango.FontFamily get_family ();
- public unowned Gtk.Widget get_family_list ();
- public string get_font_name ();
- public unowned Gtk.Widget get_preview_entry ();
- public unowned string get_preview_text ();
- public int get_size ();
- public unowned Gtk.Widget get_size_entry ();
- public unowned Gtk.Widget get_size_list ();
- public bool set_font_name (string fontname);
- public void set_preview_text (string text);
- public string font_name { owned get; set; }
- public string preview_text { get; set; }
- }
- [CCode (cheader_filename = "gtk/gtk.h", type_id = "gtk_font_selection_dialog_get_type ()")]
- [Deprecated (replacement = "FontChooserDialog", since = "3.2")]
- public class FontSelectionDialog : Gtk.Dialog, Atk.Implementor, Gtk.Buildable {
- [CCode (has_construct_function = false, type = "GtkWidget*")]
- public FontSelectionDialog (string title);
- public unowned Gtk.Widget get_cancel_button ();
- public string get_font_name ();
- public unowned Gtk.Widget get_font_selection ();
- public unowned Gtk.Widget get_ok_button ();
- public unowned string get_preview_text ();
- public bool set_font_name (string fontname);
- public void set_preview_text (string text);
- }
- [CCode (cheader_filename = "gtk/gtk.h", type_id = "gtk_frame_get_type ()")]
- public class Frame : Gtk.Bin, Atk.Implementor, Gtk.Buildable {
- [CCode (has_construct_function = false, type = "GtkWidget*")]
- public Frame (string? label);
- [NoWrapper]
- public virtual void compute_child_allocation (Gtk.Allocation allocation);
- public unowned string get_label ();
- public void get_label_align (out float xalign, out float yalign);
- public unowned Gtk.Widget? get_label_widget ();
- public Gtk.ShadowType get_shadow_type ();
- public void set_label (string? label);
- public void set_label_align (float xalign, float yalign);
- public void set_label_widget (Gtk.Widget? label_widget);
- public void set_shadow_type (Gtk.ShadowType type);
- public string label { get; set; }
- public Gtk.Widget label_widget { get; set; }
- [NoAccessorMethod]
- public float label_xalign { get; set; }
- [NoAccessorMethod]
- public float label_yalign { get; set; }
- public Gtk.ShadowType shadow_type { get; set; }
- }
- [CCode (cheader_filename = "gtk/gtk.h", type_id = "gtk_frame_accessible_get_type ()")]
- public class FrameAccessible : Gtk.ContainerAccessible, Atk.Component {
- [CCode (has_construct_function = false)]
- protected FrameAccessible ();
- }
- [CCode (cheader_filename = "gtk/gtk.h", type_id = "gtk_gesture_get_type ()")]
- public abstract class Gesture : Gtk.EventController {
- [CCode (has_construct_function = false)]
- protected Gesture ();
- public bool get_bounding_box (out Gdk.Rectangle rect);
- public bool get_bounding_box_center (out double x, out double y);
- public unowned Gdk.Device? get_device ();
- public GLib.List get_group ();
- public unowned Gdk.Event get_last_event (Gdk.EventSequence sequence);
- public unowned Gdk.EventSequence get_last_updated_sequence ();
- public bool get_point (Gdk.EventSequence? sequence, out double? x = null, out double? y = null);
- public Gtk.EventSequenceState get_sequence_state (Gdk.EventSequence sequence);
- public GLib.List get_sequences ();
- public unowned Gdk.Window? get_window ();
- public void group (Gtk.Gesture gesture);
- public bool handles_sequence (Gdk.EventSequence sequence);
- public bool is_active ();
- public bool is_grouped_with (Gtk.Gesture other);
- public bool is_recognized ();
- public bool set_sequence_state (Gdk.EventSequence sequence, Gtk.EventSequenceState state);
- public bool set_state (Gtk.EventSequenceState state);
- public void set_window (Gdk.Window? window);
- public void ungroup ();
- [NoAccessorMethod]
- public uint n_points { get; construct; }
- public Gdk.Window window { get; set; }
- public virtual signal void begin (Gdk.EventSequence p0);
- public virtual signal void cancel (Gdk.EventSequence p0);
- public virtual signal void end (Gdk.EventSequence p0);
- public virtual signal void sequence_state_changed (Gdk.EventSequence p0, Gtk.EventSequenceState p1);
- public virtual signal void update (Gdk.EventSequence p0);
- }
- [CCode (cheader_filename = "gtk/gtk.h", type_id = "gtk_gesture_drag_get_type ()")]
- public class GestureDrag : Gtk.GestureSingle {
- [CCode (has_construct_function = false, type = "GtkGesture*")]
- public GestureDrag (Gtk.Widget widget);
- public bool get_offset (out double x, out double y);
- public bool get_start_point (out double x, out double y);
- public virtual signal void drag_begin (double p0, double p1);
- public virtual signal void drag_end (double p0, double p1);
- public virtual signal void drag_update (double p0, double p1);
- }
- [CCode (cheader_filename = "gtk/gtk.h", type_id = "gtk_gesture_long_press_get_type ()")]
- public class GestureLongPress : Gtk.GestureSingle {
- [CCode (has_construct_function = false, type = "GtkGesture*")]
- public GestureLongPress (Gtk.Widget widget);
- public virtual signal void cancelled ();
- public virtual signal void pressed (double p0, double p1);
- }
- [CCode (cheader_filename = "gtk/gtk.h", type_id = "gtk_gesture_multi_press_get_type ()")]
- public class GestureMultiPress : Gtk.GestureSingle {
- [CCode (has_construct_function = false, type = "GtkGesture*")]
- public GestureMultiPress (Gtk.Widget widget);
- public bool get_area (out Gdk.Rectangle rect);
- public void set_area (Gdk.Rectangle rect);
- public virtual signal void pressed (int p0, double p1, double p2);
- public virtual signal void released (int p0, double p1, double p2);
- public virtual signal void stopped ();
- }
- [CCode (cheader_filename = "gtk/gtk.h", type_id = "gtk_gesture_pan_get_type ()")]
- public class GesturePan : Gtk.GestureDrag {
- [CCode (has_construct_function = false, type = "GtkGesture*")]
- public GesturePan (Gtk.Widget widget, Gtk.Orientation orientation);
- public Gtk.Orientation get_orientation ();
- public void set_orientation (Gtk.Orientation orientation);
- public Gtk.Orientation orientation { get; set; }
- public virtual signal void pan (Gtk.PanDirection p0, double p1);
- }
- [CCode (cheader_filename = "gtk/gtk.h", type_id = "gtk_gesture_rotate_get_type ()")]
- public class GestureRotate : Gtk.Gesture {
- [CCode (has_construct_function = false, type = "GtkGesture*")]
- public GestureRotate (Gtk.Widget widget);
- public double get_angle_delta ();
- public virtual signal void angle_changed (double p0, double p1);
- }
- [CCode (cheader_filename = "gtk/gtk.h", type_id = "gtk_gesture_single_get_type ()")]
- public class GestureSingle : Gtk.Gesture {
- [CCode (has_construct_function = false)]
- protected GestureSingle ();
- public uint get_button ();
- public uint get_current_button ();
- public Gdk.EventSequence get_current_sequence ();
- public bool get_exclusive ();
- public bool get_touch_only ();
- public void set_button (uint button);
- public void set_exclusive (bool exclusive);
- public void set_touch_only (bool touch_only);
- public uint button { get; set; }
- public bool exclusive { get; set; }
- public bool touch_only { get; set; }
- }
- [CCode (cheader_filename = "gtk/gtk.h", type_id = "gtk_gesture_swipe_get_type ()")]
- public class GestureSwipe : Gtk.GestureSingle {
- [CCode (has_construct_function = false, type = "GtkGesture*")]
- public GestureSwipe (Gtk.Widget widget);
- public bool get_velocity (out double velocity_x, out double velocity_y);
- public virtual signal void swipe (double p0, double p1);
- }
- [CCode (cheader_filename = "gtk/gtk.h", type_id = "gtk_gesture_zoom_get_type ()")]
- public class GestureZoom : Gtk.Gesture {
- [CCode (has_construct_function = false, type = "GtkGesture*")]
- public GestureZoom (Gtk.Widget widget);
- public double get_scale_delta ();
- public virtual signal void scale_changed (double p0);
- }
- [CCode (cheader_filename = "gtk/gtk.h", ref_function = "gtk_gradient_ref", type_id = "gtk_gradient_get_type ()", unref_function = "gtk_gradient_unref")]
- [Compact]
- public class Gradient {
- public void add_color_stop (double offset, Gtk.SymbolicColor color);
- [CCode (has_construct_function = false)]
- public Gradient.linear (double x0, double y0, double x1, double y1);
- [CCode (has_construct_function = false)]
- public Gradient.radial (double x0, double y0, double radius0, double x1, double y1, double radius1);
- public bool resolve (Gtk.StyleProperties props, out Cairo.Pattern resolved_gradient);
- public Cairo.Pattern resolve_for_context (Gtk.StyleContext context);
- public string to_string ();
- }
- [CCode (cheader_filename = "gtk/gtk.h", type_id = "gtk_grid_get_type ()")]
- public class Grid : Gtk.Container, Atk.Implementor, Gtk.Buildable, Gtk.Orientable {
- [CCode (has_construct_function = false, type = "GtkWidget*")]
- public Grid ();
- public void attach (Gtk.Widget child, int left, int top, int width, int height);
- public void attach_next_to (Gtk.Widget child, Gtk.Widget? sibling, Gtk.PositionType side, int width, int height);
- public int get_baseline_row ();
- public unowned Gtk.Widget get_child_at (int left, int top);
- public bool get_column_homogeneous ();
- public uint get_column_spacing ();
- public Gtk.BaselinePosition get_row_baseline_position (int row);
- public bool get_row_homogeneous ();
- public uint get_row_spacing ();
- public void insert_column (int position);
- public void insert_next_to (Gtk.Widget sibling, Gtk.PositionType side);
- public void insert_row (int position);
- public void remove_column (int position);
- public void remove_row (int position);
- public void set_baseline_row (int row);
- public void set_column_homogeneous (bool homogeneous);
- public void set_column_spacing (uint spacing);
- public void set_row_baseline_position (int row, Gtk.BaselinePosition pos);
- public void set_row_homogeneous (bool homogeneous);
- public void set_row_spacing (uint spacing);
- public int baseline_row { get; set; }
- public bool column_homogeneous { get; set; }
- public int column_spacing { get; set; }
- public bool row_homogeneous { get; set; }
- public int row_spacing { get; set; }
- }
- [CCode (cheader_filename = "gtk/gtk.h", type_id = "gtk_hbox_get_type ()")]
- [Deprecated (replacement = "Grid", since = "3.2")]
- public class HBox : Gtk.Box, Atk.Implementor, Gtk.Buildable, Gtk.Orientable {
- [CCode (has_construct_function = false, type = "GtkWidget*")]
- public HBox (bool homogeneous, int spacing);
- }
- [CCode (cheader_filename = "gtk/gtk.h", type_id = "gtk_hbutton_box_get_type ()")]
- public class HButtonBox : Gtk.ButtonBox, Atk.Implementor, Gtk.Buildable, Gtk.Orientable {
- [CCode (has_construct_function = false, type = "GtkWidget*")]
- public HButtonBox ();
- }
- [CCode (cheader_filename = "gtk/gtk.h", type_id = "gtk_hpaned_get_type ()")]
- [Deprecated (replacement = "Paned", since = "3.2")]
- public class HPaned : Gtk.Paned, Atk.Implementor, Gtk.Buildable, Gtk.Orientable {
- [CCode (has_construct_function = false, type = "GtkWidget*")]
- public HPaned ();
- }
- [CCode (cheader_filename = "gtk/gtk.h", type_id = "gtk_hsv_get_type ()")]
- public class HSV : Gtk.Widget, Atk.Implementor, Gtk.Buildable {
- [CCode (has_construct_function = false, type = "GtkWidget*")]
- public HSV ();
- public void get_color (out double h, out double s, out double v);
- public void get_metrics (out int size, out int ring_width);
- public bool is_adjusting ();
- public void set_color (double h, double s, double v);
- public void set_metrics (int size, int ring_width);
- public static void to_rgb (double h, double s, double v, out double r, out double g, out double b);
- public virtual signal void changed ();
- public virtual signal void move (Gtk.DirectionType type);
- }
- [CCode (cheader_filename = "gtk/gtk.h", type_id = "gtk_hscale_get_type ()")]
- [Deprecated (since = "3.2")]
- public class HScale : Gtk.Scale, Atk.Implementor, Gtk.Buildable, Gtk.Orientable {
- [CCode (has_construct_function = false, type = "GtkWidget*")]
- public HScale (Gtk.Adjustment? adjustment);
- [CCode (has_construct_function = false, type = "GtkWidget*")]
- public HScale.with_range (double min, double max, double step);
- }
- [CCode (cheader_filename = "gtk/gtk.h", type_id = "gtk_hscrollbar_get_type ()")]
- [Deprecated (since = "3.2")]
- public class HScrollbar : Gtk.Scrollbar, Atk.Implementor, Gtk.Buildable, Gtk.Orientable {
- [CCode (has_construct_function = false, type = "GtkWidget*")]
- public HScrollbar (Gtk.Adjustment? adjustment);
- }
- [CCode (cheader_filename = "gtk/gtk.h", type_id = "gtk_hseparator_get_type ()")]
- [Deprecated (replacement = "Separator", since = "3.2")]
- public class HSeparator : Gtk.Separator, Atk.Implementor, Gtk.Buildable, Gtk.Orientable {
- [CCode (has_construct_function = false, type = "GtkWidget*")]
- public HSeparator ();
- }
- [CCode (cheader_filename = "gtk/gtk.h", type_id = "gtk_handle_box_get_type ()")]
- [Deprecated (since = "3.4")]
- public class HandleBox : Gtk.Bin, Atk.Implementor, Gtk.Buildable {
- [CCode (has_construct_function = false, type = "GtkWidget*")]
- public HandleBox ();
- public bool get_child_detached ();
- public Gtk.PositionType get_handle_position ();
- public Gtk.ShadowType get_shadow_type ();
- public Gtk.PositionType get_snap_edge ();
- public void set_handle_position (Gtk.PositionType position);
- public void set_shadow_type (Gtk.ShadowType type);
- public void set_snap_edge (Gtk.PositionType edge);
- public bool child_detached { get; }
- public Gtk.PositionType handle_position { get; set; }
- public Gtk.ShadowType shadow_type { get; set; }
- public Gtk.PositionType snap_edge { get; set; }
- [NoAccessorMethod]
- public bool snap_edge_set { get; set; }
- public virtual signal void child_attached (Gtk.Widget child);
- }
- [CCode (cheader_filename = "gtk/gtk.h", type_id = "gtk_header_bar_get_type ()")]
- public class HeaderBar : Gtk.Container, Atk.Implementor, Gtk.Buildable {
- [CCode (has_construct_function = false, type = "GtkWidget*")]
- public HeaderBar ();
- public unowned Gtk.Widget get_custom_title ();
- public unowned string get_decoration_layout ();
- public bool get_has_subtitle ();
- public bool get_show_close_button ();
- public unowned string get_subtitle ();
- public unowned string get_title ();
- public void pack_end (Gtk.Widget child);
- public void pack_start (Gtk.Widget child);
- public void set_custom_title (Gtk.Widget title_widget);
- public void set_decoration_layout (string layout);
- public void set_has_subtitle (bool setting);
- public void set_show_close_button (bool setting);
- public void set_subtitle (string? subtitle);
- public void set_title (string title);
- public Gtk.Widget custom_title { get; set construct; }
- public string decoration_layout { get; set; }
- [NoAccessorMethod]
- public bool decoration_layout_set { get; set; }
- public bool has_subtitle { get; set; }
- public bool show_close_button { get; set; }
- [NoAccessorMethod]
- public int spacing { get; set; }
- public string subtitle { get; set; }
- public string title { get; set; }
- }
- [CCode (cheader_filename = "gtk/gtk.h,gtk/gtkimmodule.h", type_id = "gtk_im_context_get_type ()")]
- public abstract class IMContext : GLib.Object {
- [CCode (has_construct_function = false)]
- protected IMContext ();
- public virtual bool filter_keypress (Gdk.EventKey event);
- public virtual void focus_in ();
- public virtual void focus_out ();
- public virtual void get_preedit_string (out string str, out Pango.AttrList attrs, out int cursor_pos);
- public virtual bool get_surrounding (out string text, out int cursor_index);
- public virtual void reset ();
- public virtual void set_client_window (Gdk.Window window);
- public virtual void set_cursor_location (Gdk.Rectangle area);
- public virtual void set_surrounding (string text, int len, int cursor_index);
- public virtual void set_use_preedit (bool use_preedit);
- [NoAccessorMethod]
- public Gtk.InputHints input_hints { get; set; }
- [NoAccessorMethod]
- public Gtk.InputPurpose input_purpose { get; set; }
- public virtual signal void commit (string str);
- [HasEmitter]
- public virtual signal bool delete_surrounding (int offset, int n_chars);
- public virtual signal void preedit_changed ();
- public virtual signal void preedit_end ();
- public virtual signal void preedit_start ();
- public virtual signal bool retrieve_surrounding ();
- }
- [CCode (cheader_filename = "gtk/gtk.h", type_id = "gtk_im_context_simple_get_type ()")]
- public class IMContextSimple : Gtk.IMContext {
- [CCode (has_construct_function = false, type = "GtkIMContext*")]
- public IMContextSimple ();
- public void add_table ([CCode (array_length = false)] uint16[] data, int max_seq_len, int n_seqs);
- }
- [CCode (cheader_filename = "gtk/gtk.h", type_id = "gtk_im_multicontext_get_type ()")]
- public class IMMulticontext : Gtk.IMContext {
- [CCode (has_construct_function = false, type = "GtkIMContext*")]
- public IMMulticontext ();
- public void append_menuitems (Gtk.MenuShell menushell);
- public unowned string get_context_id ();
- public void set_context_id (string context_id);
- }
- [CCode (cheader_filename = "gtk/gtk.h", type_id = "gtk_icon_factory_get_type ()")]
- [Deprecated (replacement = "Gtk.IconTheme", since = "3.10")]
- public class IconFactory : GLib.Object, Gtk.Buildable {
- [CCode (has_construct_function = false)]
- public IconFactory ();
- public void add (string stock_id, Gtk.IconSet icon_set);
- public void add_default ();
- public unowned Gtk.IconSet lookup (string stock_id);
- public static unowned Gtk.IconSet lookup_default (string stock_id);
- public void remove_default ();
- }
- [CCode (cheader_filename = "gtk/gtk.h", copy_function = "gtk_icon_info_copy", free_function = "gtk_icon_info_free", type_id = "gtk_icon_info_get_type ()")]
- [Compact]
- public class IconInfo {
- [CCode (has_construct_function = false)]
- protected IconInfo ();
- public Gtk.IconInfo copy ();
- [CCode (has_construct_function = false)]
- public IconInfo.for_pixbuf (Gtk.IconTheme icon_theme, Gdk.Pixbuf pixbuf);
- public void free ();
- public bool get_attach_points (out Gdk.Point[] points);
- public int get_base_scale ();
- public int get_base_size ();
- public unowned Gdk.Pixbuf get_builtin_pixbuf ();
- public unowned string get_display_name ();
- public bool get_embedded_rect (out Gdk.Rectangle rectangle);
- public unowned string get_filename ();
- public bool is_symbolic ();
- public Gdk.Pixbuf load_icon () throws GLib.Error;
- public async Gdk.Pixbuf load_icon_async (GLib.Cancellable? cancellable = null) throws GLib.Error;
- public Cairo.Surface load_surface (Gdk.Window for_window) throws GLib.Error;
- public Gdk.Pixbuf load_symbolic (Gdk.RGBA fg, Gdk.RGBA? success_color = null, Gdk.RGBA? warning_color = null, Gdk.RGBA? error_color = null, out bool was_symbolic = null) throws GLib.Error;
- public async Gdk.Pixbuf load_symbolic_async (Gdk.RGBA fg, Gdk.RGBA? success_color = null, Gdk.RGBA? warning_color = null, Gdk.RGBA? error_color = null, GLib.Cancellable? cancellable = null) throws GLib.Error;
- public Gdk.Pixbuf load_symbolic_for_context (Gtk.StyleContext context, out bool was_symbolic = null) throws GLib.Error;
- public async Gdk.Pixbuf load_symbolic_for_context_async (Gtk.StyleContext context, GLib.Cancellable? cancellable = null) throws GLib.Error;
- [Deprecated (replacement = "load_symbolic_for_context", since = "3.0")]
- public Gdk.Pixbuf load_symbolic_for_style (Gtk.Style style, Gtk.StateType state, out bool was_symbolic = null) throws GLib.Error;
- public void set_raw_coordinates (bool raw_coordinates);
- }
- [CCode (cheader_filename = "gtk/gtk.h")]
- [Compact]
- public class IconInfoClass {
- }
- [CCode (cheader_filename = "gtk/gtk.h", ref_function = "gtk_icon_set_ref", type_id = "gtk_icon_set_get_type ()", unref_function = "gtk_icon_set_unref")]
- [Compact]
- [Deprecated (replacement = "Gtk.IconTheme", since = "3.10")]
- public class IconSet {
- [CCode (has_construct_function = false)]
- public IconSet ();
- public void add_source (Gtk.IconSource source);
- public Gtk.IconSet copy ();
- [CCode (has_construct_function = false)]
- public IconSet.from_pixbuf (Gdk.Pixbuf pixbuf);
- public void get_sizes (out Gtk.IconSize[] sizes);
- [Deprecated (replacement = "set_render_icon_pixbuf", since = "3.0")]
- public Gdk.Pixbuf render_icon (Gtk.Style style, Gtk.TextDirection direction, Gtk.StateType state, Gtk.IconSize size, Gtk.Widget widget, string detail);
- [Deprecated (since = "3.10")]
- public Gdk.Pixbuf render_icon_pixbuf (Gtk.StyleContext context, Gtk.IconSize size);
- [Deprecated (since = "3.10")]
- public Cairo.Surface render_icon_surface (Gtk.StyleContext context, Gtk.IconSize size, int scale, Gdk.Window for_window);
- }
- [CCode (cheader_filename = "gtk/gtk.h", copy_function = "gtk_icon_source_copy", type_id = "gtk_icon_source_get_type ()")]
- [Compact]
- [Deprecated (replacement = "Gtk.IconTheme", since = "3.10")]
- public class IconSource {
- [CCode (has_construct_function = false)]
- public IconSource ();
- public Gtk.IconSource copy ();
- public Gtk.TextDirection get_direction ();
- public bool get_direction_wildcarded ();
- public unowned string get_filename ();
- public unowned string get_icon_name ();
- public unowned Gdk.Pixbuf get_pixbuf ();
- public Gtk.IconSize get_size ();
- public bool get_size_wildcarded ();
- public Gtk.StateType get_state ();
- public bool get_state_wildcarded ();
- public void set_direction (Gtk.TextDirection direction);
- public void set_direction_wildcarded (bool setting);
- public void set_filename (string filename);
- public void set_icon_name (string icon_name);
- public void set_pixbuf (Gdk.Pixbuf pixbuf);
- public void set_size (Gtk.IconSize size);
- public void set_size_wildcarded (bool setting);
- public void set_state (Gtk.StateType state);
- public void set_state_wildcarded (bool setting);
- }
- [CCode (cheader_filename = "gtk/gtk.h", type_id = "gtk_icon_theme_get_type ()")]
- public class IconTheme : GLib.Object {
- [CCode (has_construct_function = false)]
- public IconTheme ();
- public static void add_builtin_icon (string icon_name, int size, Gdk.Pixbuf pixbuf);
- public void add_resource_path (string path);
- public void append_search_path (string path);
- public Gtk.IconInfo? choose_icon ([CCode (array_length = false, array_null_terminated = true)] string[] icon_names, int size, Gtk.IconLookupFlags flags);
- public Gtk.IconInfo? choose_icon_for_scale (string[] icon_names, int size, int scale, Gtk.IconLookupFlags flags);
- public static GLib.Quark error_quark ();
- public static unowned Gtk.IconTheme get_default ();
- public string? get_example_icon_name ();
- public static unowned Gtk.IconTheme get_for_screen (Gdk.Screen screen);
- [CCode (array_length = false, array_null_terminated = true)]
- public int[] get_icon_sizes (string icon_name);
- public void get_search_path (out string[] path);
- public bool has_icon (string icon_name);
- public GLib.List list_contexts ();
- public GLib.List list_icons (string? context);
- public Gdk.Pixbuf? load_icon (string icon_name, int size, Gtk.IconLookupFlags flags) throws GLib.Error;
- public Gdk.Pixbuf? load_icon_for_scale (string icon_name, int size, int scale, Gtk.IconLookupFlags flags) throws GLib.Error;
- public Cairo.Surface? load_surface (string icon_name, int size, int scale, Gdk.Window for_window, Gtk.IconLookupFlags flags) throws GLib.Error;
- public Gtk.IconInfo? lookup_by_gicon (GLib.Icon icon, int size, Gtk.IconLookupFlags flags);
- public Gtk.IconInfo? lookup_by_gicon_for_scale (GLib.Icon icon, int size, int scale, Gtk.IconLookupFlags flags);
- public Gtk.IconInfo? lookup_icon (string icon_name, int size, Gtk.IconLookupFlags flags);
- public Gtk.IconInfo? lookup_icon_for_scale (string icon_name, int size, int scale, Gtk.IconLookupFlags flags);
- public void prepend_search_path (string path);
- public bool rescan_if_needed ();
- public void set_custom_theme (string theme_name);
- public void set_screen (Gdk.Screen screen);
- public void set_search_path (string[] path);
- public virtual signal void changed ();
- }
- [CCode (cheader_filename = "gtk/gtk.h", type_id = "gtk_icon_view_get_type ()")]
- public class IconView : Gtk.Container, Atk.Implementor, Gtk.Buildable, Gtk.CellLayout, Gtk.Scrollable {
- [CCode (has_construct_function = false, type = "GtkWidget*")]
- public IconView ();
- public void convert_widget_to_bin_window_coords (int wx, int wy, out int bx, out int by);
- public Cairo.Surface create_drag_icon (Gtk.TreePath path);
- public void enable_model_drag_dest (Gtk.TargetEntry[] targets, Gdk.DragAction actions);
- public void enable_model_drag_source (Gdk.ModifierType start_button_mask, Gtk.TargetEntry[] targets, Gdk.DragAction actions);
- public bool get_activate_on_single_click ();
- public bool get_cell_rect (Gtk.TreePath path, Gtk.CellRenderer? cell, out Gdk.Rectangle rect);
- public int get_column_spacing ();
- public int get_columns ();
- public bool get_cursor (out Gtk.TreePath path, out unowned Gtk.CellRenderer cell);
- public bool get_dest_item_at_pos (int drag_x, int drag_y, out unowned Gtk.TreePath path, Gtk.IconViewDropPosition pos);
- public void get_drag_dest_item (out unowned Gtk.TreePath path, Gtk.IconViewDropPosition pos);
- public bool get_item_at_pos (int x, int y, out unowned Gtk.TreePath path, out unowned Gtk.CellRenderer cell);
- public int get_item_column (Gtk.TreePath path);
- public Gtk.Orientation get_item_orientation ();
- public int get_item_padding ();
- public int get_item_row (Gtk.TreePath path);
- public int get_item_width ();
- public int get_margin ();
- public int get_markup_column ();
- public unowned Gtk.TreeModel get_model ();
- public Gtk.TreePath get_path_at_pos (int x, int y);
- public int get_pixbuf_column ();
- public bool get_reorderable ();
- public int get_row_spacing ();
- public GLib.List get_selected_items ();
- public Gtk.SelectionMode get_selection_mode ();
- public int get_spacing ();
- public int get_text_column ();
- public int get_tooltip_column ();
- public bool get_tooltip_context (out int x, out int y, bool keyboard_tip, out unowned Gtk.TreeModel model, out unowned Gtk.TreePath path, out Gtk.TreeIter iter);
- public bool get_visible_range (out Gtk.TreePath start_path, out Gtk.TreePath end_path);
- public bool path_is_selected (Gtk.TreePath path);
- public void scroll_to_path (Gtk.TreePath path, bool use_align, float row_align, float col_align);
- public void select_path (Gtk.TreePath path);
- public void selected_foreach (Gtk.IconViewForeachFunc func);
- public void set_activate_on_single_click (bool single);
- public void set_column_spacing (int column_spacing);
- public void set_columns (int columns);
- public void set_cursor (Gtk.TreePath path, Gtk.CellRenderer? cell, bool start_editing);
- public void set_drag_dest_item (Gtk.TreePath path, Gtk.IconViewDropPosition pos);
- public void set_item_orientation (Gtk.Orientation orientation);
- public void set_item_padding (int item_padding);
- public void set_item_width (int item_width);
- public void set_margin (int margin);
- public void set_markup_column (int column);
- public void set_model (Gtk.TreeModel? model);
- public void set_pixbuf_column (int column);
- public void set_reorderable (bool reorderable);
- public void set_row_spacing (int row_spacing);
- public void set_selection_mode (Gtk.SelectionMode mode);
- public void set_spacing (int spacing);
- public void set_text_column (int column);
- public void set_tooltip_cell (Gtk.Tooltip tooltip, Gtk.TreePath path, Gtk.CellRenderer cell);
- public void set_tooltip_column (int column);
- public void set_tooltip_item (Gtk.Tooltip tooltip, Gtk.TreePath path);
- public void unselect_path (Gtk.TreePath path);
- public void unset_model_drag_dest ();
- public void unset_model_drag_source ();
- [CCode (has_construct_function = false, type = "GtkWidget*")]
- public IconView.with_area (Gtk.CellArea area);
- [CCode (has_construct_function = false, type = "GtkWidget*")]
- public IconView.with_model (Gtk.TreeModel model);
- public bool activate_on_single_click { get; set; }
- [NoAccessorMethod]
- public Gtk.CellArea cell_area { owned get; construct; }
- public int column_spacing { get; set; }
- public int columns { get; set; }
- public Gtk.Orientation item_orientation { get; set; }
- public int item_padding { get; set; }
- public int item_width { get; set; }
- public int margin { get; set; }
- public int markup_column { get; set; }
- public Gtk.TreeModel model { get; set; }
- public int pixbuf_column { get; set; }
- public bool reorderable { get; set; }
- public int row_spacing { get; set; }
- public Gtk.SelectionMode selection_mode { get; set; }
- public int spacing { get; set; }
- public int text_column { get; set; }
- public int tooltip_column { get; set; }
- public virtual signal bool activate_cursor_item ();
- [HasEmitter]
- public virtual signal void item_activated (Gtk.TreePath path);
- public virtual signal bool move_cursor (Gtk.MovementStep step, int count);
- public virtual signal void select_all ();
- public virtual signal void select_cursor_item ();
- public virtual signal void selection_changed ();
- public virtual signal void toggle_cursor_item ();
- public virtual signal void unselect_all ();
- }
- [CCode (cheader_filename = "gtk/gtk.h", type_id = "gtk_icon_view_accessible_get_type ()")]
- public class IconViewAccessible : Gtk.ContainerAccessible, Atk.Component, Atk.Selection {
- [CCode (has_construct_function = false)]
- protected IconViewAccessible ();
- }
- [CCode (cheader_filename = "gtk/gtk.h", type_id = "gtk_image_get_type ()")]
- public class Image : Gtk.Misc, Atk.Implementor, Gtk.Buildable {
- [CCode (has_construct_function = false, type = "GtkWidget*")]
- public Image ();
- public void clear ();
- [CCode (has_construct_function = false, type = "GtkWidget*")]
- public Image.from_animation (Gdk.PixbufAnimation animation);
- [CCode (has_construct_function = false, type = "GtkWidget*")]
- public Image.from_file (string filename);
- [CCode (has_construct_function = false, type = "GtkWidget*")]
- public Image.from_gicon (GLib.Icon icon, Gtk.IconSize size);
- [CCode (has_construct_function = false, type = "GtkWidget*")]
- public Image.from_icon_name (string icon_name, Gtk.IconSize size);
- [CCode (has_construct_function = false, type = "GtkWidget*")]
- public Image.from_icon_set (Gtk.IconSet icon_set, Gtk.IconSize size);
- [CCode (has_construct_function = false, type = "GtkWidget*")]
- public Image.from_pixbuf (Gdk.Pixbuf pixbuf);
- [CCode (has_construct_function = false, type = "GtkWidget*")]
- public Image.from_resource (string resource_path);
- [CCode (has_construct_function = false, type = "GtkWidget*")]
- public Image.from_stock (string stock_id, Gtk.IconSize size);
- [CCode (has_construct_function = false, type = "GtkWidget*")]
- public Image.from_surface (Cairo.Surface surface);
- public unowned Gdk.PixbufAnimation get_animation ();
- public void get_gicon (out unowned GLib.Icon gicon, Gtk.IconSize size);
- public void get_icon_name (out unowned string icon_name, out Gtk.IconSize size);
- public void get_icon_set (out unowned Gtk.IconSet icon_set, out Gtk.IconSize size);
- public unowned Gdk.Pixbuf get_pixbuf ();
- public int get_pixel_size ();
- public void get_stock (out string stock_id, out Gtk.IconSize size);
- public Gtk.ImageType get_storage_type ();
- public void set_from_animation (Gdk.PixbufAnimation animation);
- public void set_from_file (string filename);
- public void set_from_gicon (GLib.Icon icon, Gtk.IconSize size);
- public void set_from_icon_name (string icon_name, Gtk.IconSize size);
- public void set_from_icon_set (Gtk.IconSet icon_set, Gtk.IconSize size);
- public void set_from_pixbuf (Gdk.Pixbuf pixbuf);
- public void set_from_resource (string resource_path);
- public void set_from_stock (string stock_id, Gtk.IconSize size);
- public void set_from_surface (Cairo.Surface surface);
- public void set_pixel_size (int pixel_size);
- [NoAccessorMethod]
- public string file { owned get; set; }
- [NoAccessorMethod]
- public GLib.Icon gicon { owned get; set; }
- [NoAccessorMethod]
- public string icon_name { owned get; set; }
- [NoAccessorMethod]
- public Gtk.IconSet icon_set { owned get; set; }
- [NoAccessorMethod]
- public int icon_size { get; set; }
- [NoAccessorMethod]
- public Gdk.Pixbuf pixbuf { owned get; set; }
- [NoAccessorMethod]
- public Gdk.PixbufAnimation pixbuf_animation { owned get; set; }
- public int pixel_size { get; set; }
- [NoAccessorMethod]
- public string resource { owned get; set; }
- [NoAccessorMethod]
- public string stock { owned get; set; }
- public Gtk.ImageType storage_type { get; }
- [NoAccessorMethod]
- public Cairo.Surface surface { owned get; set; }
- [NoAccessorMethod]
- public bool use_fallback { get; set; }
- }
- [CCode (cheader_filename = "gtk/gtk.h", type_id = "gtk_image_accessible_get_type ()")]
- public class ImageAccessible : Gtk.WidgetAccessible, Atk.Component, Atk.Image {
- [CCode (has_construct_function = false)]
- protected ImageAccessible ();
- }
- [CCode (cheader_filename = "gtk/gtk.h", type_id = "gtk_image_cell_accessible_get_type ()")]
- public class ImageCellAccessible : Gtk.RendererCellAccessible, Atk.Action, Atk.Component, Atk.Image {
- [CCode (has_construct_function = false)]
- protected ImageCellAccessible ();
- }
- [CCode (cheader_filename = "gtk/gtk.h", type_id = "gtk_image_menu_item_get_type ()")]
- public class ImageMenuItem : Gtk.MenuItem, Atk.Implementor, Gtk.Buildable, Gtk.Activatable, Gtk.Actionable {
- [CCode (has_construct_function = false, type = "GtkWidget*")]
- public ImageMenuItem ();
- [CCode (has_construct_function = false, type = "GtkWidget*")]
- public ImageMenuItem.from_stock (string stock_id, Gtk.AccelGroup? accel_group);
- public bool get_always_show_image ();
- public unowned Gtk.Widget get_image ();
- public bool get_use_stock ();
- public void set_accel_group (Gtk.AccelGroup accel_group);
- public void set_always_show_image (bool always_show);
- public void set_image (Gtk.Widget image);
- public void set_use_stock (bool use_stock);
- [CCode (has_construct_function = false, type = "GtkWidget*")]
- public ImageMenuItem.with_label (string label);
- [CCode (has_construct_function = false, type = "GtkWidget*")]
- public ImageMenuItem.with_mnemonic (string label);
- public Gtk.AccelGroup accel_group { set; }
- public bool always_show_image { get; set construct; }
- public Gtk.Widget image { get; set; }
- public bool use_stock { get; set construct; }
- }
- [CCode (cheader_filename = "gtk/gtk.h", type_id = "gtk_info_bar_get_type ()")]
- public class InfoBar : Gtk.Box, Atk.Implementor, Gtk.Buildable, Gtk.Orientable {
- [CCode (has_construct_function = false, type = "GtkWidget*")]
- public InfoBar ();
- public void add_action_widget (Gtk.Widget child, int response_id);
- public unowned Gtk.Button add_button (string button_text, int response_id);
- public void add_buttons (...);
- public unowned Gtk.Widget get_action_area ();
- public unowned Gtk.Container get_content_area ();
- public Gtk.MessageType get_message_type ();
- public bool get_show_close_button ();
- public void set_default_response (int response_id);
- public void set_message_type (Gtk.MessageType message_type);
- public void set_response_sensitive (int response_id, bool setting);
- public void set_show_close_button (bool setting);
- [CCode (has_construct_function = false, type = "GtkWidget*")]
- public InfoBar.with_buttons (...);
- public Gtk.MessageType message_type { get; set construct; }
- public bool show_close_button { get; set construct; }
- public virtual signal void close ();
- [HasEmitter]
- public virtual signal void response (int response_id);
- }
- [CCode (cheader_filename = "gtk/gtk.h", type_id = "gtk_invisible_get_type ()")]
- public class Invisible : Gtk.Widget, Atk.Implementor, Gtk.Buildable {
- [CCode (has_construct_function = false, type = "GtkWidget*")]
- public Invisible ();
- [CCode (has_construct_function = false, type = "GtkWidget*")]
- public Invisible.for_screen (Gdk.Screen screen);
- public unowned Gdk.Screen get_screen ();
- public void set_screen (Gdk.Screen screen);
- public Gdk.Screen screen { get; set; }
- }
- [CCode (cheader_filename = "gtk/gtk.h", type_id = "gtk_label_get_type ()")]
- public class Label : Gtk.Misc, Atk.Implementor, Gtk.Buildable {
- [CCode (has_construct_function = false, type = "GtkWidget*")]
- public Label (string? str);
- public double get_angle ();
- public unowned Pango.AttrList get_attributes ();
- public unowned string get_current_uri ();
- public Pango.EllipsizeMode get_ellipsize ();
- public Gtk.Justification get_justify ();
- public unowned string get_label ();
- public unowned Pango.Layout get_layout ();
- public void get_layout_offsets (out int x, out int y);
- public bool get_line_wrap ();
- public Pango.WrapMode get_line_wrap_mode ();
- public int get_lines ();
- public int get_max_width_chars ();
- public uint get_mnemonic_keyval ();
- public unowned Gtk.Widget get_mnemonic_widget ();
- public bool get_selectable ();
- public bool get_selection_bounds (out int start, out int end);
- public bool get_single_line_mode ();
- public unowned string get_text ();
- public bool get_track_visited_links ();
- public bool get_use_markup ();
- public bool get_use_underline ();
- public int get_width_chars ();
- public void select_region (int start_offset, int end_offset);
- public void set_angle (double angle);
- public void set_attributes (Pango.AttrList attrs);
- public void set_ellipsize (Pango.EllipsizeMode mode);
- public void set_justify (Gtk.Justification jtype);
- public void set_label (string str);
- public void set_line_wrap (bool wrap);
- public void set_line_wrap_mode (Pango.WrapMode wrap_mode);
- public void set_lines (int lines);
- public void set_markup (string str);
- public void set_markup_with_mnemonic (string str);
- public void set_max_width_chars (int n_chars);
- public void set_mnemonic_widget (Gtk.Widget widget);
- public void set_pattern (string pattern);
- public void set_selectable (bool setting);
- public void set_single_line_mode (bool single_line_mode);
- public void set_text (string str);
- public void set_text_with_mnemonic (string str);
- public void set_track_visited_links (bool track_links);
- public void set_use_markup (bool setting);
- public void set_use_underline (bool setting);
- public void set_width_chars (int n_chars);
- [CCode (has_construct_function = false, type = "GtkWidget*")]
- public Label.with_mnemonic (string str);
- public double angle { get; set; }
- public Pango.AttrList attributes { get; set; }
- [NoAccessorMethod]
- public int cursor_position { get; }
- public Pango.EllipsizeMode ellipsize { get; set; }
- public Gtk.Justification justify { get; set; }
- public string label { get; set; }
- public int lines { get; set; }
- public int max_width_chars { get; set; }
- public uint mnemonic_keyval { get; }
- public Gtk.Widget mnemonic_widget { get; set; }
- public string pattern { set; }
- public bool selectable { get; set; }
- [NoAccessorMethod]
- public int selection_bound { get; }
- public bool single_line_mode { get; set; }
- public bool track_visited_links { get; set; }
- public bool use_markup { get; set; }
- public bool use_underline { get; set; }
- public int width_chars { get; set; }
- [NoAccessorMethod]
- public bool wrap { get; set; }
- [NoAccessorMethod]
- public Pango.WrapMode wrap_mode { get; set; }
- public virtual signal void activate_current_link ();
- public virtual signal bool activate_link (string uri);
- public virtual signal void copy_clipboard ();
- public virtual signal void move_cursor (Gtk.MovementStep step, int count, bool extend_selection);
- public virtual signal void populate_popup (Gtk.Menu menu);
- }
- [CCode (cheader_filename = "gtk/gtk.h", type_id = "gtk_label_accessible_get_type ()")]
- public class LabelAccessible : Gtk.WidgetAccessible, Atk.Component, Atk.Text, Atk.Hypertext {
- [CCode (has_construct_function = false)]
- protected LabelAccessible ();
- }
- [CCode (cheader_filename = "gtk/gtk.h")]
- [Compact]
- public class LabelSelectionInfo {
- }
- [CCode (cheader_filename = "gtk/gtk.h", type_id = "gtk_layout_get_type ()")]
- public class Layout : Gtk.Container, Atk.Implementor, Gtk.Buildable, Gtk.Scrollable {
- [CCode (has_construct_function = false, type = "GtkWidget*")]
- public Layout (Gtk.Adjustment? hadjustment = null, Gtk.Adjustment? vadjustment = null);
- public unowned Gdk.Window get_bin_window ();
- public unowned Gtk.Adjustment get_hadjustment ();
- public void get_size (out uint width, out uint height);
- public unowned Gtk.Adjustment get_vadjustment ();
- public void move (Gtk.Widget child_widget, int x, int y);
- public void put (Gtk.Widget child_widget, int x, int y);
- public void set_hadjustment (Gtk.Adjustment adjustment);
- public void set_size (uint width, uint height);
- public void set_vadjustment (Gtk.Adjustment adjustment);
- [NoAccessorMethod]
- public uint height { get; set; }
- [NoAccessorMethod]
- public uint width { get; set; }
- }
- [CCode (cheader_filename = "gtk/gtk.h", type_id = "gtk_level_bar_get_type ()")]
- public class LevelBar : Gtk.Widget, Atk.Implementor, Gtk.Buildable, Gtk.Orientable {
- [CCode (has_construct_function = false, type = "GtkWidget*")]
- public LevelBar ();
- public void add_offset_value (string name, double value);
- [CCode (has_construct_function = false, type = "GtkWidget*")]
- public LevelBar.for_interval (double min_value, double max_value);
- public bool get_inverted ();
- public double get_max_value ();
- public double get_min_value ();
- public Gtk.LevelBarMode get_mode ();
- public bool get_offset_value (string name, double value);
- public double get_value ();
- public void remove_offset_value (string name);
- public void set_inverted (bool inverted);
- public void set_max_value (double value);
- public void set_min_value (double value);
- public void set_mode (Gtk.LevelBarMode mode);
- public void set_value (double value);
- public bool inverted { get; set; }
- public double max_value { get; set; }
- public double min_value { get; set; }
- public Gtk.LevelBarMode mode { get; set; }
- public double value { get; set; }
- public virtual signal void offset_changed (string name);
- }
- [CCode (cheader_filename = "gtk/gtk.h", type_id = "gtk_level_bar_accessible_get_type ()")]
- public class LevelBarAccessible : Gtk.WidgetAccessible, Atk.Component, Atk.Value {
- [CCode (has_construct_function = false)]
- protected LevelBarAccessible ();
- }
- [CCode (cheader_filename = "gtk/gtk.h", type_id = "gtk_link_button_get_type ()")]
- public class LinkButton : Gtk.Button, Atk.Implementor, Gtk.Buildable, Gtk.Actionable, Gtk.Activatable {
- [CCode (has_construct_function = false, type = "GtkWidget*")]
- public LinkButton (string uri);
- public unowned string get_uri ();
- public bool get_visited ();
- public void set_uri (string uri);
- public void set_visited (bool visited);
- [CCode (has_construct_function = false, type = "GtkWidget*")]
- public LinkButton.with_label (string uri, string label);
- public string uri { get; set; }
- public bool visited { get; set; }
- public virtual signal bool activate_link ();
- }
- [CCode (cheader_filename = "gtk/gtk.h", type_id = "gtk_link_button_accessible_get_type ()")]
- public class LinkButtonAccessible : Gtk.ButtonAccessible, Atk.Component, Atk.Action, Atk.Image, Atk.HyperlinkImpl {
- [CCode (has_construct_function = false)]
- protected LinkButtonAccessible ();
- }
- [CCode (cheader_filename = "gtk/gtk.h", type_id = "gtk_list_box_get_type ()")]
- public class ListBox : Gtk.Container, Atk.Implementor, Gtk.Buildable {
- [CCode (has_construct_function = false, type = "GtkWidget*")]
- public ListBox ();
- public void drag_highlight_row (Gtk.ListBoxRow row);
- public void drag_unhighlight_row ();
- public bool get_activate_on_single_click ();
- public unowned Gtk.Adjustment get_adjustment ();
- public unowned Gtk.ListBoxRow get_row_at_index (int index_);
- public unowned Gtk.ListBoxRow get_row_at_y (int y);
- public unowned Gtk.ListBoxRow get_selected_row ();
- public GLib.List get_selected_rows ();
- public Gtk.SelectionMode get_selection_mode ();
- public void insert (Gtk.Widget child, int position);
- public void invalidate_filter ();
- public void invalidate_headers ();
- public void invalidate_sort ();
- public void prepend (Gtk.Widget child);
- public void select_row (Gtk.ListBoxRow? row);
- public void selected_foreach (Gtk.ListBoxForeachFunc func);
- public void set_activate_on_single_click (bool single);
- public void set_adjustment (Gtk.Adjustment? adjustment);
- public void set_filter_func (owned Gtk.ListBoxFilterFunc? filter_func);
- public void set_header_func (owned Gtk.ListBoxUpdateHeaderFunc? update_header);
- public void set_placeholder (Gtk.Widget? placeholder);
- public void set_selection_mode (Gtk.SelectionMode mode);
- public void set_sort_func (owned Gtk.ListBoxSortFunc? sort_func);
- public void unselect_row (Gtk.ListBoxRow row);
- public bool activate_on_single_click { get; set; }
- public Gtk.SelectionMode selection_mode { get; set; }
- public virtual signal void activate_cursor_row ();
- public virtual signal void move_cursor (Gtk.MovementStep step, int count);
- public virtual signal void row_activated (Gtk.ListBoxRow row);
- public virtual signal void row_selected (Gtk.ListBoxRow? row);
- [HasEmitter]
- public virtual signal void select_all ();
- public virtual signal void selected_rows_changed ();
- public virtual signal void toggle_cursor_row ();
- [HasEmitter]
- public virtual signal void unselect_all ();
- }
- [CCode (cheader_filename = "gtk/gtk.h", type_id = "gtk_list_box_accessible_get_type ()")]
- public class ListBoxAccessible : Gtk.ContainerAccessible, Atk.Component, Atk.Selection {
- [CCode (has_construct_function = false)]
- protected ListBoxAccessible ();
- }
- [CCode (cheader_filename = "gtk/gtk.h", type_id = "gtk_list_box_row_get_type ()")]
- public class ListBoxRow : Gtk.Bin, Atk.Implementor, Gtk.Buildable {
- [CCode (has_construct_function = false, type = "GtkWidget*")]
- public ListBoxRow ();
- public void changed ();
- public bool get_activatable ();
- public unowned Gtk.Widget get_header ();
- public int get_index ();
- public bool get_selectable ();
- public bool is_selected ();
- public void set_activatable (bool activatable);
- public void set_header (Gtk.Widget? header);
- public void set_selectable (bool selectable);
- public bool activatable { get; set; }
- public bool selectable { get; set; }
- public virtual signal void activate ();
- }
- [CCode (cheader_filename = "gtk/gtk.h", type_id = "gtk_list_box_row_accessible_get_type ()")]
- public class ListBoxRowAccessible : Gtk.ContainerAccessible, Atk.Component {
- [CCode (has_construct_function = false)]
- protected ListBoxRowAccessible ();
- }
- [CCode (cheader_filename = "gtk/gtk.h", type_id = "gtk_list_store_get_type ()")]
- public class ListStore : GLib.Object, Gtk.TreeModel, Gtk.TreeDragSource, Gtk.TreeDragDest, Gtk.TreeSortable, Gtk.Buildable {
- [CCode (has_construct_function = false, sentinel = "-1")]
- public ListStore (int n_columns, ...);
- public void append (out Gtk.TreeIter iter);
- public void clear ();
- public void insert (out Gtk.TreeIter iter, int position);
- public void insert_after (out Gtk.TreeIter iter, Gtk.TreeIter? sibling);
- public void insert_before (out Gtk.TreeIter iter, Gtk.TreeIter? sibling);
- [CCode (sentinel = "-1")]
- public void insert_with_values (out Gtk.TreeIter iter, int position, ...);
- public void insert_with_valuesv (out Gtk.TreeIter iter, int position, [CCode (array_length_pos = 4.1)] int[] columns, [CCode (array_length_pos = 4.1)] GLib.Value[] values);
- public bool iter_is_valid (Gtk.TreeIter iter);
- public void move_after (ref Gtk.TreeIter iter, Gtk.TreeIter? position);
- public void move_before (ref Gtk.TreeIter iter, Gtk.TreeIter? position);
- [CCode (cname = "gtk_list_store_newv", has_construct_function = false)]
- public ListStore.newv ([CCode (array_length_pos = 0.9)] GLib.Type[] types);
- public void prepend (out Gtk.TreeIter iter);
- public bool remove (Gtk.TreeIter iter);
- public void reorder ([CCode (array_length = false, array_null_terminated = true)] int[] new_order);
- [CCode (sentinel = "-1")]
- public void @set (Gtk.TreeIter iter, ...);
- public void set_column_types ([CCode (array_length_pos = 0.9)] GLib.Type[] types);
- public void set_valist (Gtk.TreeIter iter, va_list var_args);
- public void set_value (Gtk.TreeIter iter, int column, GLib.Value value);
- public void set_valuesv (Gtk.TreeIter iter, [CCode (array_length_pos = 3.1)] int[] columns, [CCode (array_length_pos = 3.1)] GLib.Value[] values);
- public void swap (Gtk.TreeIter a, Gtk.TreeIter b);
- }
- [CCode (cheader_filename = "gtk/gtk.h", type_id = "gtk_lock_button_get_type ()")]
- public class LockButton : Gtk.Button, Atk.Implementor, Gtk.Buildable, Gtk.Actionable, Gtk.Activatable {
- [CCode (has_construct_function = false, type = "GtkWidget*")]
- public LockButton (GLib.Permission permission);
- public unowned GLib.Permission get_permission ();
- public void set_permission (GLib.Permission permission);
- public GLib.Permission permission { get; set; }
- [NoAccessorMethod]
- public string text_lock { owned get; set construct; }
- [NoAccessorMethod]
- public string text_unlock { owned get; set construct; }
- [NoAccessorMethod]
- public string tooltip_lock { owned get; set construct; }
- [NoAccessorMethod]
- public string tooltip_not_authorized { owned get; set construct; }
- [NoAccessorMethod]
- public string tooltip_unlock { owned get; set construct; }
- }
- [CCode (cheader_filename = "gtk/gtk.h", type_id = "gtk_lock_button_accessible_get_type ()")]
- public class LockButtonAccessible : Gtk.ButtonAccessible, Atk.Component, Atk.Action, Atk.Image {
- [CCode (has_construct_function = false)]
- protected LockButtonAccessible ();
- }
- [CCode (cheader_filename = "gtk/gtk.h", type_id = "gtk_menu_get_type ()")]
- public class Menu : Gtk.MenuShell, Atk.Implementor, Gtk.Buildable {
- [CCode (has_construct_function = false, type = "GtkWidget*")]
- public Menu ();
- public void attach (Gtk.Widget child, uint left_attach, uint right_attach, uint top_attach, uint bottom_attach);
- public void attach_to_widget (Gtk.Widget attach_widget, Gtk.MenuDetachFunc? detacher);
- public void detach ();
- [CCode (has_construct_function = false, type = "GtkWidget*")]
- public Menu.from_model (GLib.MenuModel model);
- public unowned Gtk.AccelGroup get_accel_group ();
- public unowned string get_accel_path ();
- public unowned Gtk.Widget get_active ();
- public unowned Gtk.Widget get_attach_widget ();
- public static unowned GLib.List get_for_attach_widget (Gtk.Widget widget);
- public int get_monitor ();
- public bool get_reserve_toggle_size ();
- public bool get_tearoff_state ();
- public unowned string get_title ();
- public void popdown ();
- public void popup (Gtk.Widget? parent_menu_shell, Gtk.Widget? parent_menu_item, Gtk.MenuPositionFunc? func, uint button, uint32 activate_time);
- public void popup_for_device (Gdk.Device device, Gtk.Widget parent_menu_shell, Gtk.Widget parent_menu_item, Gtk.MenuPositionFunc func, void* data, GLib.DestroyNotify destroy, uint button, uint32 activate_time);
- public void reorder_child (Gtk.Widget child, int position);
- public void reposition ();
- public void set_accel_group (Gtk.AccelGroup accel_group);
- public void set_accel_path (string accel_path);
- public void set_active (uint index);
- public void set_monitor (int monitor_num);
- public void set_reserve_toggle_size (bool reserve_toggle_size);
- public void set_screen (Gdk.Screen? screen);
- public void set_tearoff_state (bool torn_off);
- public void set_title (string title);
- public Gtk.AccelGroup accel_group { get; set; }
- public string accel_path { get; set; }
- public int active { get; set; }
- [NoAccessorMethod]
- public Gtk.Widget attach_widget { owned get; set; }
- public int monitor { get; set; }
- public bool reserve_toggle_size { get; set; }
- public bool tearoff_state { get; set; }
- [NoAccessorMethod]
- public string tearoff_title { owned get; set; }
- public virtual signal void move_scroll (Gtk.ScrollType p0);
- }
- [CCode (cheader_filename = "gtk/gtk.h", type_id = "gtk_menu_accessible_get_type ()")]
- public class MenuAccessible : Gtk.MenuShellAccessible, Atk.Component, Atk.Selection {
- [CCode (has_construct_function = false)]
- protected MenuAccessible ();
- }
- [CCode (cheader_filename = "gtk/gtk.h", type_id = "gtk_menu_bar_get_type ()")]
- public class MenuBar : Gtk.MenuShell, Atk.Implementor, Gtk.Buildable {
- [CCode (has_construct_function = false, type = "GtkWidget*")]
- public MenuBar ();
- [CCode (has_construct_function = false, type = "GtkWidget*")]
- public MenuBar.from_model (GLib.MenuModel model);
- public Gtk.PackDirection get_child_pack_direction ();
- public Gtk.PackDirection get_pack_direction ();
- public void set_child_pack_direction (Gtk.PackDirection child_pack_dir);
- public void set_pack_direction (Gtk.PackDirection pack_dir);
- public Gtk.PackDirection child_pack_direction { get; set; }
- public Gtk.PackDirection pack_direction { get; set; }
- }
- [CCode (cheader_filename = "gtk/gtk.h", type_id = "gtk_menu_button_get_type ()")]
- public class MenuButton : Gtk.ToggleButton, Atk.Implementor, Gtk.Buildable, Gtk.Actionable, Gtk.Activatable {
- [CCode (has_construct_function = false, type = "GtkWidget*")]
- public MenuButton ();
- public unowned Gtk.Widget get_align_widget ();
- public Gtk.ArrowType get_direction ();
- public unowned GLib.MenuModel get_menu_model ();
- public unowned Gtk.Popover get_popover ();
- public unowned Gtk.Menu get_popup ();
- public bool get_use_popover ();
- public void set_align_widget (Gtk.Widget align_widget);
- public void set_direction (Gtk.ArrowType direction);
- public void set_menu_model (GLib.MenuModel menu_model);
- public void set_popover (Gtk.Widget popover);
- public void set_popup (Gtk.Widget menu);
- public void set_use_popover (bool use_popover);
- public Gtk.Container align_widget { get; set; }
- public Gtk.ArrowType direction { get; set; }
- public GLib.MenuModel menu_model { get; set; }
- public Gtk.Popover popover { get; set; }
- public Gtk.Menu popup { get; set; }
- public bool use_popover { get; set; }
- }
- [CCode (cheader_filename = "gtk/gtk.h", type_id = "gtk_menu_button_accessible_get_type ()")]
- public class MenuButtonAccessible : Gtk.ToggleButtonAccessible, Atk.Component, Atk.Action, Atk.Image {
- [CCode (has_construct_function = false)]
- protected MenuButtonAccessible ();
- }
- [CCode (cheader_filename = "gtk/gtk.h", type_id = "gtk_menu_item_get_type ()")]
- public class MenuItem : Gtk.Bin, Atk.Implementor, Gtk.Buildable, Gtk.Activatable, Gtk.Actionable {
- [CCode (has_construct_function = false, type = "GtkWidget*")]
- public MenuItem ();
- public unowned string get_accel_path ();
- public virtual unowned string get_label ();
- public bool get_reserve_indicator ();
- [Deprecated (replacement = "Widget.get_hexpand and Widget.get_halign", since = "3.2")]
- public bool get_right_justified ();
- public unowned Gtk.Widget get_submenu ();
- public bool get_use_underline ();
- public void set_accel_path (string accel_path);
- public virtual void set_label (string label);
- public void set_reserve_indicator (bool reserve);
- [Deprecated (replacement = "Widget.set_hexpand and Widget.set_halign", since = "3.2")]
- public void set_right_justified (bool right_justified);
- public void set_submenu (Gtk.Widget submenu);
- public void set_use_underline (bool setting);
- [CCode (has_construct_function = false, type = "GtkWidget*")]
- public MenuItem.with_label (string label);
- [CCode (has_construct_function = false, type = "GtkWidget*")]
- public MenuItem.with_mnemonic (string label);
- public string accel_path { get; set; }
- public string label { get; set; }
- public bool right_justified { get; set; }
- public Gtk.Menu submenu { get; set; }
- public bool use_underline { get; set; }
- [HasEmitter]
- public virtual signal void activate ();
- public virtual signal void activate_item ();
- public virtual signal void deselect ();
- public virtual signal void select ();
- [HasEmitter]
- public virtual signal void toggle_size_allocate (int allocation);
- [HasEmitter]
- public virtual signal void toggle_size_request (void* requisition);
- }
- [CCode (cheader_filename = "gtk/gtk.h", type_id = "gtk_menu_item_accessible_get_type ()")]
- public class MenuItemAccessible : Gtk.ContainerAccessible, Atk.Component, Atk.Action, Atk.Selection {
- [CCode (has_construct_function = false)]
- protected MenuItemAccessible ();
- }
- [CCode (cheader_filename = "gtk/gtk.h", type_id = "gtk_menu_shell_get_type ()")]
- public abstract class MenuShell : Gtk.Container, Atk.Implementor, Gtk.Buildable {
- [CCode (has_construct_function = false)]
- protected MenuShell ();
- public void activate_item (Gtk.Widget menu_item, bool force_deactivate);
- public void append ([CCode (type = "GtkWidget*")] Gtk.MenuItem child);
- public void bind_model (GLib.MenuModel model, string action_namespace, bool with_separators);
- public void deselect ();
- public unowned Gtk.Widget get_parent_shell ();
- [NoWrapper]
- public virtual int get_popup_delay ();
- public unowned Gtk.Widget get_selected_item ();
- public bool get_take_focus ();
- public void prepend (Gtk.Widget child);
- public void select_first (bool search_sensitive);
- public virtual void select_item (Gtk.Widget menu_item);
- public void set_take_focus (bool take_focus);
- public bool take_focus { get; set; }
- public virtual signal void activate_current (bool force_hide);
- [HasEmitter]
- public virtual signal void cancel ();
- public virtual signal void cycle_focus (Gtk.DirectionType p0);
- [HasEmitter]
- public virtual signal void deactivate ();
- [HasEmitter]
- public virtual signal void insert (Gtk.Widget child, int position);
- public virtual signal void move_current (Gtk.MenuDirectionType direction);
- public virtual signal bool move_selected (int distance);
- public virtual signal void selection_done ();
- }
- [CCode (cheader_filename = "gtk/gtk.h", type_id = "gtk_menu_shell_accessible_get_type ()")]
- public class MenuShellAccessible : Gtk.ContainerAccessible, Atk.Component, Atk.Selection {
- [CCode (has_construct_function = false)]
- protected MenuShellAccessible ();
- }
- [CCode (cheader_filename = "gtk/gtk.h", type_id = "gtk_menu_tool_button_get_type ()")]
- public class MenuToolButton : Gtk.ToolButton, Atk.Implementor, Gtk.Buildable, Gtk.Activatable, Gtk.Actionable {
- [CCode (has_construct_function = false, type = "GtkToolItem*")]
- public MenuToolButton (Gtk.Widget? icon_widget, string? label);
- [CCode (has_construct_function = false, type = "GtkToolItem*")]
- public MenuToolButton.from_stock (string stock_id);
- public unowned Gtk.Widget get_menu ();
- public void set_arrow_tooltip_markup (string markup);
- public void set_arrow_tooltip_text (string text);
- public void set_menu (Gtk.Widget menu);
- public Gtk.Menu menu { get; set; }
- public virtual signal void show_menu ();
- }
- [CCode (cheader_filename = "gtk/gtk.h", type_id = "gtk_message_dialog_get_type ()")]
- public class MessageDialog : Gtk.Dialog, Atk.Implementor, Gtk.Buildable {
- [CCode (has_construct_function = false, type = "GtkWidget*")]
- [PrintfFormat]
- public MessageDialog (Gtk.Window? parent, Gtk.DialogFlags flags, Gtk.MessageType type, Gtk.ButtonsType buttons, string message_format, ...);
- [PrintfFormat]
- public void format_secondary_markup (string message_format, ...);
- [PrintfFormat]
- public void format_secondary_text (string message_format, ...);
- public unowned Gtk.Widget get_image ();
- public unowned Gtk.Widget get_message_area ();
- public void set_image (Gtk.Widget image);
- public void set_markup (string str);
- [CCode (has_construct_function = false, type = "GtkWidget*")]
- [PrintfFormat]
- public MessageDialog.with_markup (Gtk.Window? parent, Gtk.DialogFlags flags, Gtk.MessageType type, Gtk.ButtonsType buttons, string message_format, ...);
- [NoAccessorMethod]
- public Gtk.ButtonsType buttons { construct; }
- public Gtk.Widget image { get; set; }
- public Gtk.Widget message_area { get; }
- [NoAccessorMethod]
- public Gtk.MessageType message_type { get; set construct; }
- [NoAccessorMethod]
- public string secondary_text { owned get; set; }
- [NoAccessorMethod]
- public bool secondary_use_markup { get; set; }
- [NoAccessorMethod]
- public string text { owned get; set; }
- [NoAccessorMethod]
- public bool use_markup { get; set; }
- }
- [CCode (cheader_filename = "gtk/gtk.h", type_id = "gtk_misc_get_type ()")]
- public abstract class Misc : Gtk.Widget, Atk.Implementor, Gtk.Buildable {
- [CCode (has_construct_function = false)]
- protected Misc ();
- public void get_alignment (out float xalign, out float yalign);
- public void get_padding (out int xpad, out int ypad);
- public void set_alignment (float xalign, float yalign);
- public void set_padding (int xpad, int ypad);
- [NoAccessorMethod]
- public float xalign { get; set; }
- [NoAccessorMethod]
- public int xpad { get; set; }
- [NoAccessorMethod]
- public float yalign { get; set; }
- [NoAccessorMethod]
- public int ypad { get; set; }
- }
- [CCode (cheader_filename = "gtk/gtk.h", type_id = "gtk_mount_operation_get_type ()")]
- public class MountOperation : GLib.MountOperation {
- [CCode (has_construct_function = false, type = "GMountOperation*")]
- public MountOperation (Gtk.Window? parent);
- public unowned Gtk.Window get_parent ();
- public unowned Gdk.Screen get_screen ();
- public void set_parent (Gtk.Window parent);
- public void set_screen (Gdk.Screen screen);
- [NoAccessorMethod]
- public bool is_showing { get; }
- public Gtk.Window parent { get; set; }
- public Gdk.Screen screen { get; set; }
- }
- [CCode (cheader_filename = "gtk/gtk.h", type_id = "gtk_notebook_get_type ()")]
- public class Notebook : Gtk.Container, Atk.Implementor, Gtk.Buildable {
- [CCode (has_construct_function = false, type = "GtkWidget*")]
- public Notebook ();
- public int append_page (Gtk.Widget child, Gtk.Widget? tab_label = null);
- public int append_page_menu (Gtk.Widget child, Gtk.Widget? tab_label, Gtk.Widget? menu_label);
- public unowned Gtk.Widget get_action_widget (Gtk.PackType pack_type);
- public int get_current_page ();
- public unowned string get_group_name ();
- public unowned Gtk.Widget get_menu_label (Gtk.Widget child);
- public unowned string get_menu_label_text (Gtk.Widget child);
- public int get_n_pages ();
- public unowned Gtk.Widget get_nth_page (int page_num);
- public bool get_scrollable ();
- public bool get_show_border ();
- public bool get_show_tabs ();
- public bool get_tab_detachable (Gtk.Widget child);
- [Deprecated (since = "3.4")]
- public uint16 get_tab_hborder ();
- public unowned Gtk.Widget get_tab_label (Gtk.Widget child);
- public unowned string get_tab_label_text (Gtk.Widget child);
- public Gtk.PositionType get_tab_pos ();
- public bool get_tab_reorderable (Gtk.Widget child);
- [Deprecated (since = "3.4")]
- public uint16 get_tab_vborder ();
- public int insert_page (Gtk.Widget child, Gtk.Widget? tab_label, int position);
- [CCode (vfunc_name = "insert_page")]
- public virtual int insert_page_menu (Gtk.Widget child, Gtk.Widget? tab_label, Gtk.Widget? menu_label, int position);
- public void next_page ();
- public int page_num (Gtk.Widget child);
- public void popup_disable ();
- public void popup_enable ();
- public int prepend_page (Gtk.Widget child, Gtk.Widget? tab_label = null);
- public int prepend_page_menu (Gtk.Widget child, Gtk.Widget? tab_label, Gtk.Widget? menu_label);
- public void prev_page ();
- public void remove_page (int page_num);
- public void reorder_child (Gtk.Widget child, int position);
- public void set_action_widget (Gtk.Widget widget, Gtk.PackType pack_type);
- public void set_current_page (int page_num);
- public void set_group_name (string group_name);
- public void set_menu_label (Gtk.Widget child, Gtk.Widget? menu_label);
- public void set_menu_label_text (Gtk.Widget child, string menu_text);
- public void set_scrollable (bool scrollable);
- public void set_show_border (bool show_border);
- public void set_show_tabs (bool show_tabs);
- public void set_tab_detachable (Gtk.Widget child, bool detachable);
- public void set_tab_label (Gtk.Widget child, Gtk.Widget? tab_label);
- public void set_tab_label_text (Gtk.Widget child, string tab_text);
- public void set_tab_pos (Gtk.PositionType pos);
- public void set_tab_reorderable (Gtk.Widget child, bool reorderable);
- [NoAccessorMethod]
- public bool enable_popup { get; set; }
- public string group_name { get; set; }
- [NoAccessorMethod]
- public int page { get; set; }
- public bool scrollable { get; set; }
- public bool show_border { get; set; }
- public bool show_tabs { get; set; }
- public Gtk.PositionType tab_pos { get; set; }
- public virtual signal bool change_current_page (int offset);
- public virtual signal unowned Gtk.Notebook create_window (Gtk.Widget page, int x, int y);
- public virtual signal bool focus_tab (Gtk.NotebookTab type);
- public virtual signal void move_focus_out (Gtk.DirectionType direction);
- public virtual signal void page_added (Gtk.Widget child, uint page_num);
- public virtual signal void page_removed (Gtk.Widget child, uint page_num);
- public virtual signal void page_reordered (Gtk.Widget child, uint page_num);
- public virtual signal bool reorder_tab (Gtk.DirectionType direction, bool move_to_last);
- public virtual signal bool select_page (bool move_focus);
- public virtual signal void switch_page (Gtk.Widget page, uint page_num);
- }
- [CCode (cheader_filename = "gtk/gtk.h", type_id = "gtk_notebook_accessible_get_type ()")]
- public class NotebookAccessible : Gtk.ContainerAccessible, Atk.Component, Atk.Selection {
- [CCode (has_construct_function = false)]
- protected NotebookAccessible ();
- }
- [CCode (cheader_filename = "gtk/gtk.h", type_id = "gtk_notebook_page_accessible_get_type ()")]
- public class NotebookPageAccessible : Atk.Object, Atk.Component {
- [CCode (has_construct_function = false, type = "AtkObject*")]
- public NotebookPageAccessible (Gtk.NotebookAccessible notebook, Gtk.Widget child);
- public void invalidate ();
- }
- [CCode (cheader_filename = "gtk/gtk.h", type_id = "gtk_numerable_icon_get_type ()")]
- public class NumerableIcon : GLib.EmblemedIcon, GLib.Icon {
- [CCode (has_construct_function = false, type = "GIcon*")]
- public NumerableIcon (GLib.Icon base_icon);
- public unowned GLib.Icon get_background_gicon ();
- public unowned string get_background_icon_name ();
- public int get_count ();
- public unowned string get_label ();
- public unowned Gtk.StyleContext get_style_context ();
- public void set_background_gicon (GLib.Icon icon);
- public void set_background_icon_name (string icon_name);
- public void set_count (int count);
- public void set_label (string label);
- public void set_style_context (Gtk.StyleContext style);
- [CCode (has_construct_function = false, type = "GIcon*")]
- public NumerableIcon.with_style_context (GLib.Icon base_icon, Gtk.StyleContext context);
- [NoAccessorMethod]
- public GLib.Icon background_icon { owned get; set; }
- public string background_icon_name { get; set; }
- public int count { get; set; }
- public string label { get; set; }
- public Gtk.StyleContext style_context { get; set; }
- }
- [CCode (cheader_filename = "gtk/gtk.h", type_id = "gtk_offscreen_window_get_type ()")]
- public class OffscreenWindow : Gtk.Window, Atk.Implementor, Gtk.Buildable {
- [CCode (has_construct_function = false, type = "GtkWidget*")]
- public OffscreenWindow ();
- public Gdk.Pixbuf get_pixbuf ();
- public unowned Cairo.Surface get_surface ();
- }
- [CCode (cheader_filename = "gtk/gtk.h", type_id = "gtk_overlay_get_type ()")]
- public class Overlay : Gtk.Bin, Atk.Implementor, Gtk.Buildable {
- [CCode (has_construct_function = false, type = "GtkWidget*")]
- public Overlay ();
- public void add_overlay (Gtk.Widget widget);
- public virtual signal bool get_child_position (Gtk.Widget widget, out Gdk.Rectangle allocation);
- }
- [CCode (cheader_filename = "gtk/gtk.h", type_id = "gtk_page_setup_get_type ()")]
- public class PageSetup : GLib.Object {
- [CCode (has_construct_function = false)]
- public PageSetup ();
- public Gtk.PageSetup copy ();
- [CCode (has_construct_function = false)]
- public PageSetup.from_file (string file_name) throws GLib.Error;
- [CCode (has_construct_function = false)]
- public PageSetup.from_key_file (GLib.KeyFile key_file, string group_name) throws GLib.Error;
- public double get_bottom_margin (Gtk.Unit unit);
- public double get_left_margin (Gtk.Unit unit);
- public Gtk.PageOrientation get_orientation ();
- public double get_page_height (Gtk.Unit unit);
- public double get_page_width (Gtk.Unit unit);
- public double get_paper_height (Gtk.Unit unit);
- public unowned Gtk.PaperSize get_paper_size ();
- public double get_paper_width (Gtk.Unit unit);
- public double get_right_margin (Gtk.Unit unit);
- public double get_top_margin (Gtk.Unit unit);
- public bool load_file (string file_name) throws GLib.Error;
- public bool load_key_file (GLib.KeyFile key_file, string group_name) throws GLib.Error;
- public void set_bottom_margin (double margin, Gtk.Unit unit);
- public void set_left_margin (double margin, Gtk.Unit unit);
- public void set_orientation (Gtk.PageOrientation orientation);
- public void set_paper_size (Gtk.PaperSize size);
- public void set_paper_size_and_default_margins (Gtk.PaperSize size);
- public void set_right_margin (double margin, Gtk.Unit unit);
- public void set_top_margin (double margin, Gtk.Unit unit);
- public bool to_file (string file_name) throws GLib.Error;
- public void to_key_file (GLib.KeyFile key_file, string group_name);
- }
- [CCode (cheader_filename = "gtk/gtk.h", type_id = "gtk_paned_get_type ()")]
- public class Paned : Gtk.Container, Atk.Implementor, Gtk.Buildable, Gtk.Orientable {
- [CCode (has_construct_function = false, type = "GtkWidget*")]
- public Paned (Gtk.Orientation orientation);
- public void add1 (Gtk.Widget child);
- public void add2 (Gtk.Widget child);
- public unowned Gtk.Widget get_child1 ();
- public unowned Gtk.Widget get_child2 ();
- public unowned Gdk.Window get_handle_window ();
- public int get_position ();
- public void pack1 (Gtk.Widget child, bool resize, bool shrink);
- public void pack2 (Gtk.Widget child, bool resize, bool shrink);
- public void set_position (int position);
- [NoAccessorMethod]
- public int max_position { get; }
- [NoAccessorMethod]
- public int min_position { get; }
- public int position { get; set; }
- [NoAccessorMethod]
- public bool position_set { get; set; }
- public virtual signal bool accept_position ();
- public virtual signal bool cancel_position ();
- public virtual signal bool cycle_child_focus (bool reverse);
- public virtual signal bool cycle_handle_focus (bool reverse);
- public virtual signal bool move_handle (Gtk.ScrollType scroll);
- public virtual signal bool toggle_handle_focus ();
- }
- [CCode (cheader_filename = "gtk/gtk.h", type_id = "gtk_paned_accessible_get_type ()")]
- public class PanedAccessible : Gtk.ContainerAccessible, Atk.Component, Atk.Value {
- [CCode (has_construct_function = false)]
- protected PanedAccessible ();
- }
- [CCode (cheader_filename = "gtk/gtk.h", copy_function = "gtk_paper_size_copy", type_id = "gtk_paper_size_get_type ()")]
- [Compact]
- public class PaperSize {
- [CCode (has_construct_function = false)]
- public PaperSize (string name);
- public Gtk.PaperSize copy ();
- [CCode (has_construct_function = false)]
- public PaperSize.custom (string name, string display_name, double width, double height, Gtk.Unit unit);
- [CCode (has_construct_function = false)]
- public PaperSize.from_key_file (GLib.KeyFile key_file, string group_name) throws GLib.Error;
- [CCode (has_construct_function = false)]
- public PaperSize.from_ppd (string ppd_name, string ppd_display_name, double width, double height);
- public static unowned string get_default ();
- public double get_default_bottom_margin (Gtk.Unit unit);
- public double get_default_left_margin (Gtk.Unit unit);
- public double get_default_right_margin (Gtk.Unit unit);
- public double get_default_top_margin (Gtk.Unit unit);
- public unowned string get_display_name ();
- public double get_height (Gtk.Unit unit);
- public unowned string get_name ();
- public static GLib.List get_paper_sizes (bool include_custom);
- public unowned string get_ppd_name ();
- public double get_width (Gtk.Unit unit);
- public bool is_custom ();
- public bool is_equal (Gtk.PaperSize size2);
- public void set_size (double width, double height, Gtk.Unit unit);
- public void to_key_file (GLib.KeyFile key_file, string group_name);
- }
- [CCode (cheader_filename = "gtk/gtk.h", type_id = "gtk_places_sidebar_get_type ()")]
- public class PlacesSidebar : Gtk.ScrolledWindow, Atk.Implementor, Gtk.Buildable {
- [CCode (has_construct_function = false, type = "GtkWidget*")]
- public PlacesSidebar ();
- public void add_shortcut (GLib.File location);
- public bool get_local_only ();
- public GLib.File get_location ();
- public GLib.File get_nth_bookmark (int n);
- public Gtk.PlacesOpenFlags get_open_flags ();
- public bool get_show_connect_to_server ();
- public bool get_show_desktop ();
- public bool get_show_enter_location ();
- public GLib.SList list_shortcuts ();
- public void remove_shortcut (GLib.File location);
- public void set_local_only (bool local_only);
- public void set_location (GLib.File location);
- public void set_open_flags (Gtk.PlacesOpenFlags flags);
- public void set_show_connect_to_server (bool show_connect_to_server);
- public void set_show_desktop (bool show_desktop);
- public void set_show_enter_location (bool show_enter_location);
- public bool local_only { get; set; }
- public GLib.File location { owned get; set; }
- public Gtk.PlacesOpenFlags open_flags { get; set; }
- public bool show_connect_to_server { get; set; }
- public bool show_desktop { get; set; }
- public bool show_enter_location { get; set; }
- public virtual signal int drag_action_ask (int p0);
- public virtual signal int drag_action_requested (Gdk.DragContext p0, GLib.File p1, GLib.List p2);
- public virtual signal void drag_perform_drop (GLib.File p0, GLib.List p1, int p2);
- public virtual signal void open_location (GLib.File p0, Gtk.PlacesOpenFlags p1);
- public virtual signal void populate_popup (Gtk.Menu p0, GLib.File? p1, GLib.Volume? p2);
- public virtual signal void show_error_message (string p0, string p1);
- }
- [CCode (cheader_filename = "gtk/gtkx.h", type_id = "gtk_plug_get_type ()")]
- public class Plug : Gtk.Window, Atk.Implementor, Gtk.Buildable {
- [CCode (has_construct_function = false, type = "GtkWidget*")]
- public Plug (X.Window socket_id);
- public void @construct (X.Window socket_id);
- public void construct_for_display (Gdk.Display display, X.Window socket_id);
- [CCode (has_construct_function = false, type = "GtkWidget*")]
- public Plug.for_display (Gdk.Display display, X.Window socket_id);
- public bool get_embedded ();
- public X.Window get_id ();
- public unowned Gdk.Window get_socket_window ();
- public bool embedded { get; }
- public Gdk.Window socket_window { get; }
- }
- [CCode (cheader_filename = "gtk/gtk.h", type_id = "gtk_popover_get_type ()")]
- public class Popover : Gtk.Bin, Atk.Implementor, Gtk.Buildable {
- [CCode (has_construct_function = false, type = "GtkWidget*")]
- public Popover (Gtk.Widget relative_to);
- public void bind_model (GLib.MenuModel model, string action_namespace);
- [CCode (has_construct_function = false, type = "GtkWidget*")]
- public Popover.from_model (Gtk.Widget relative_to, GLib.MenuModel model);
- public bool get_modal ();
- public bool get_pointing_to (out Gdk.Rectangle rect);
- public Gtk.PositionType get_position ();
- public unowned Gtk.Widget get_relative_to ();
- public void set_modal (bool modal);
- public void set_pointing_to (Gdk.Rectangle rect);
- public void set_position (Gtk.PositionType position);
- public void set_relative_to (Gtk.Widget relative_to);
- public bool modal { get; set; }
- public Cairo.RectangleInt pointing_to { get; set; }
- public Gtk.PositionType position { get; set construct; }
- public Gtk.Widget relative_to { get; set; }
- public virtual signal void closed ();
- }
- [CCode (cheader_filename = "gtk/gtk.h", type_id = "gtk_popover_accessible_get_type ()")]
- public class PopoverAccessible : Gtk.ContainerAccessible, Atk.Component {
- [CCode (has_construct_function = false)]
- protected PopoverAccessible ();
- }
- [CCode (cheader_filename = "gtk/gtk.h", type_id = "gtk_print_context_get_type ()")]
- public class PrintContext : GLib.Object {
- [CCode (has_construct_function = false)]
- protected PrintContext ();
- public Pango.Context create_pango_context ();
- public Pango.Layout create_pango_layout ();
- public unowned Cairo.Context get_cairo_context ();
- public double get_dpi_x ();
- public double get_dpi_y ();
- public bool get_hard_margins (out double top, out double bottom, out double left, out double right);
- public double get_height ();
- public unowned Gtk.PageSetup get_page_setup ();
- public unowned Pango.FontMap get_pango_fontmap ();
- public double get_width ();
- public void set_cairo_context (Cairo.Context cr, double dpi_x, double dpi_y);
- }
- [CCode (cheader_filename = "gtk/gtk.h", type_id = "gtk_print_operation_get_type ()")]
- public class PrintOperation : GLib.Object, Gtk.PrintOperationPreview {
- [CCode (has_construct_function = false)]
- public PrintOperation ();
- public void cancel ();
- public void draw_page_finish ();
- public unowned Gtk.PageSetup get_default_page_setup ();
- public bool get_embed_page_setup ();
- public void get_error () throws GLib.Error;
- public bool get_has_selection ();
- public int get_n_pages_to_print ();
- public unowned Gtk.PrintSettings get_print_settings ();
- public Gtk.PrintStatus get_status ();
- public unowned string get_status_string ();
- public bool get_support_selection ();
- public bool is_finished ();
- public Gtk.PrintOperationResult run (Gtk.PrintOperationAction action, Gtk.Window parent) throws GLib.Error;
- public void set_allow_async (bool allow_async);
- public void set_current_page (int current_page);
- public void set_custom_tab_label (string label);
- public void set_default_page_setup (Gtk.PageSetup default_page_setup);
- public void set_defer_drawing ();
- public void set_embed_page_setup (bool embed);
- public void set_export_filename (string filename);
- public void set_has_selection (bool has_selection);
- public void set_job_name (string job_name);
- public void set_n_pages (int n_pages);
- public void set_print_settings (Gtk.PrintSettings print_settings);
- public void set_show_progress (bool show_progress);
- public void set_support_selection (bool support_selection);
- public void set_track_print_status (bool track_status);
- public void set_unit (Gtk.Unit unit);
- public void set_use_full_page (bool full_page);
- [NoAccessorMethod]
- public bool allow_async { get; set; }
- [NoAccessorMethod]
- public int current_page { get; set; }
- [NoAccessorMethod]
- public string custom_tab_label { owned get; set; }
- public Gtk.PageSetup default_page_setup { get; set; }
- public bool embed_page_setup { get; set; }
- [NoAccessorMethod]
- public string export_filename { owned get; set; }
- public bool has_selection { get; set; }
- [NoAccessorMethod]
- public string job_name { owned get; set; }
- [NoAccessorMethod]
- public int n_pages { get; set; }
- public int n_pages_to_print { get; }
- public Gtk.PrintSettings print_settings { get; set; }
- [NoAccessorMethod]
- public bool show_progress { get; set; }
- public Gtk.PrintStatus status { get; }
- public string status_string { get; }
- public bool support_selection { get; set; }
- [NoAccessorMethod]
- public bool track_print_status { get; set; }
- [NoAccessorMethod]
- public Gtk.Unit unit { get; set; }
- [NoAccessorMethod]
- public bool use_full_page { get; set; }
- public virtual signal void begin_print (Gtk.PrintContext context);
- public virtual signal unowned GLib.Object create_custom_widget ();
- public virtual signal void custom_widget_apply (Gtk.Widget widget);
- public virtual signal void done (Gtk.PrintOperationResult result);
- public virtual signal void draw_page (Gtk.PrintContext context, int page_nr);
- public virtual signal void end_print (Gtk.PrintContext context);
- public virtual signal bool paginate (Gtk.PrintContext context);
- public virtual signal bool preview (Gtk.PrintOperationPreview preview, Gtk.PrintContext context, Gtk.Window parent);
- public virtual signal void request_page_setup (Gtk.PrintContext context, int page_nr, Gtk.PageSetup setup);
- public virtual signal void status_changed ();
- public virtual signal void update_custom_widget (Gtk.Widget widget, Gtk.PageSetup setup, Gtk.PrintSettings settings);
- }
- [CCode (cheader_filename = "gtk/gtk.h", type_id = "gtk_print_settings_get_type ()")]
- public class PrintSettings : GLib.Object {
- [CCode (has_construct_function = false)]
- public PrintSettings ();
- public Gtk.PrintSettings copy ();
- public void @foreach (Gtk.PrintSettingsFunc func);
- [CCode (has_construct_function = false)]
- public PrintSettings.from_file (string file_name) throws GLib.Error;
- [CCode (has_construct_function = false)]
- public PrintSettings.from_key_file (GLib.KeyFile key_file, string group_name) throws GLib.Error;
- public unowned string @get (string key);
- public bool get_bool (string key);
- public bool get_collate ();
- public unowned string get_default_source ();
- public unowned string get_dither ();
- public double get_double (string key);
- public double get_double_with_default (string key, double def);
- public Gtk.PrintDuplex get_duplex ();
- public unowned string get_finishings ();
- public int get_int (string key);
- public int get_int_with_default (string key, int def);
- public double get_length (string key, Gtk.Unit unit);
- public unowned string get_media_type ();
- public int get_n_copies ();
- public int get_number_up ();
- public Gtk.NumberUpLayout get_number_up_layout ();
- public Gtk.PageOrientation get_orientation ();
- public unowned string get_output_bin ();
- public Gtk.PageRange[] get_page_ranges ();
- public Gtk.PageSet get_page_set ();
- public double get_paper_height (Gtk.Unit unit);
- public Gtk.PaperSize get_paper_size ();
- public double get_paper_width (Gtk.Unit unit);
- public Gtk.PrintPages get_print_pages ();
- public unowned string get_printer ();
- public double get_printer_lpi ();
- public Gtk.PrintQuality get_quality ();
- public int get_resolution ();
- public int get_resolution_x ();
- public int get_resolution_y ();
- public bool get_reverse ();
- public double get_scale ();
- public bool get_use_color ();
- public bool has_key (string key);
- public bool load_file (string file_name) throws GLib.Error;
- public bool load_key_file (GLib.KeyFile key_file, string group_name) throws GLib.Error;
- public void @set (string key, string value);
- public void set_bool (string key, bool value);
- public void set_collate (bool collate);
- public void set_default_source (string default_source);
- public void set_dither (string dither);
- public void set_double (string key, double value);
- public void set_duplex (Gtk.PrintDuplex duplex);
- public void set_finishings (string finishings);
- public void set_int (string key, int value);
- public void set_length (string key, double value, Gtk.Unit unit);
- public void set_media_type (string media_type);
- public void set_n_copies (int num_copies);
- public void set_number_up (int number_up);
- public void set_number_up_layout (Gtk.NumberUpLayout number_up_layout);
- public void set_orientation (Gtk.PageOrientation orientation);
- public void set_output_bin (string output_bin);
- public void set_page_ranges ([CCode (array_length_pos = 1.1)] Gtk.PageRange[] page_ranges);
- public void set_page_set (Gtk.PageSet page_set);
- public void set_paper_height (double height, Gtk.Unit unit);
- public void set_paper_size (Gtk.PaperSize paper_size);
- public void set_paper_width (double width, Gtk.Unit unit);
- public void set_print_pages (Gtk.PrintPages pages);
- public void set_printer (string printer);
- public void set_printer_lpi (double lpi);
- public void set_quality (Gtk.PrintQuality quality);
- public void set_resolution (int resolution);
- public void set_resolution_xy (int resolution_x, int resolution_y);
- public void set_reverse (bool reverse);
- public void set_scale (double scale);
- public void set_use_color (bool use_color);
- public bool to_file (string file_name) throws GLib.Error;
- public void to_key_file (GLib.KeyFile key_file, string group_name);
- public void unset (string key);
- }
- [CCode (cheader_filename = "gtk/gtk.h", type_id = "gtk_progress_bar_get_type ()")]
- public class ProgressBar : Gtk.Widget, Atk.Implementor, Gtk.Buildable, Gtk.Orientable {
- [CCode (has_construct_function = false, type = "GtkWidget*")]
- public ProgressBar ();
- public Pango.EllipsizeMode get_ellipsize ();
- public double get_fraction ();
- public bool get_inverted ();
- public double get_pulse_step ();
- public bool get_show_text ();
- public unowned string get_text ();
- public void pulse ();
- public void set_ellipsize (Pango.EllipsizeMode mode);
- public void set_fraction (double fraction);
- public void set_inverted (bool inverted);
- public void set_pulse_step (double fraction);
- public void set_show_text (bool show_text);
- public void set_text (string text);
- public Pango.EllipsizeMode ellipsize { get; set; }
- public double fraction { get; set; }
- public bool inverted { get; set; }
- public double pulse_step { get; set; }
- public bool show_text { get; set; }
- public string text { get; set; }
- }
- [CCode (cheader_filename = "gtk/gtk.h", type_id = "gtk_progress_bar_accessible_get_type ()")]
- public class ProgressBarAccessible : Gtk.WidgetAccessible, Atk.Component, Atk.Value {
- [CCode (has_construct_function = false)]
- protected ProgressBarAccessible ();
- }
- [CCode (cheader_filename = "gtk/gtk.h", type_id = "gtk_radio_action_get_type ()")]
- public class RadioAction : Gtk.ToggleAction, Gtk.Buildable {
- [CCode (has_construct_function = false)]
- public RadioAction (string name, string? label, string? tooltip, string? stock_id, int value);
- public int get_current_value ();
- public unowned GLib.SList get_group ();
- public void join_group (Gtk.RadioAction group_source);
- public void set_current_value (int current_value);
- public void set_group (GLib.SList group);
- public int current_value { get; set; }
- [NoAccessorMethod]
- public Gtk.RadioAction group { set; }
- [NoAccessorMethod]
- public int value { get; set; }
- public virtual signal void changed (Gtk.RadioAction current);
- }
- [CCode (cheader_filename = "gtk/gtk.h", type_id = "gtk_radio_button_get_type ()")]
- public class RadioButton : Gtk.CheckButton, Atk.Implementor, Gtk.Buildable, Gtk.Actionable, Gtk.Activatable {
- [CCode (has_construct_function = false, type = "GtkWidget*")]
- public RadioButton (GLib.SList? group);
- [CCode (has_construct_function = false, type = "GtkWidget*")]
- public RadioButton.from_widget (Gtk.RadioButton? radio_group_member);
- public unowned GLib.SList get_group ();
- public void join_group (Gtk.RadioButton group_source);
- public void set_group (GLib.SList group);
- [CCode (has_construct_function = false, type = "GtkWidget*")]
- public RadioButton.with_label (GLib.SList