mirror of
https://gitlab.linphone.org/BC/public/linphone-desktop.git
synced 2026-01-17 03:18:07 +00:00
fix get size with screen ratio function fix chat sending area ui #LINQT-2068 print debug logs in linphone files for futur debugging fix call history details ui when no video conference factory set use remote name of each call if in local conference #LINQT-2058
880 lines
No EOL
25 KiB
JavaScript
880 lines
No EOL
25 KiB
JavaScript
/*
|
|
* Copyright (c) 2010-2024 Belledonne Communications SARL.
|
|
*
|
|
* This file is part of linphone-desktop
|
|
* (see https://www.linphone.org).
|
|
*
|
|
* This program is free software: you can redistribute it and/or modify
|
|
* it under the terms of the GNU General Public License as published by
|
|
* the Free Software Foundation, either version 3 of the License, or
|
|
* (at your option) any later version.
|
|
*
|
|
* This program is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
* GNU General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU General Public License
|
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
*/
|
|
// =============================================================================
|
|
// Contains many common helpers.
|
|
// =============================================================================
|
|
|
|
.pragma library
|
|
|
|
.import QtQuick as QtQuick
|
|
.import Linphone as Linphone
|
|
|
|
// =============================================================================
|
|
// Constants.
|
|
// =============================================================================
|
|
|
|
|
|
var SCHEME_REGEX = new RegExp('^[^:]+:')
|
|
|
|
// =============================================================================
|
|
// QML helpers.
|
|
// =============================================================================
|
|
|
|
function buildCommonDialogUri (component) {
|
|
return 'qrc:/ui/modules/Common/Dialog/' + component + '.qml'
|
|
}
|
|
function buildCommonUri (component, subComponent) {
|
|
return 'qrc:/ui/modules/Common/'+subComponent+'/' + component + '.qml'
|
|
}
|
|
|
|
function buildLinphoneDialogUri (component) {
|
|
return 'qrc:/ui/modules/Linphone/Dialog/' + component + '.qml'
|
|
}
|
|
|
|
function buildAppDialogUri (component) {
|
|
return 'qrc:/ui/views/App/Dialog/' + component + '.qml'
|
|
}
|
|
|
|
// -----------------------------------------------------------------------------
|
|
|
|
// Destroy timeout.
|
|
function clearTimeout (timer) {
|
|
timer.stop() // NECESSARY.
|
|
timer.destroy()
|
|
}
|
|
|
|
// -----------------------------------------------------------------------------
|
|
|
|
function createObject (source, parent, options) {
|
|
if (options && options.isString) {
|
|
var object = Qt.createQmlObject(source, parent)
|
|
|
|
var properties = options && options.properties
|
|
if (properties) {
|
|
for (var key in properties) {
|
|
object[key] = properties[key]
|
|
}
|
|
}
|
|
|
|
return object
|
|
}
|
|
|
|
var component = Qt.createComponent(source)
|
|
if (component.status !== QtQuick.Component.Ready) {
|
|
console.debug('Component not ready.')
|
|
if (component.status === QtQuick.Component.Error) {
|
|
console.debug('Error: ' + component.errorString())
|
|
}
|
|
return // Error.
|
|
}
|
|
|
|
var object = component.createObject(parent, (options && options.properties) || {})
|
|
if (!object) {
|
|
console.debug('Error: unable to create dynamic object.')
|
|
}
|
|
|
|
return object
|
|
}
|
|
|
|
// -----------------------------------------------------------------------------
|
|
|
|
function getSystemPathFromUri (uri) {
|
|
var str = uri.toString()
|
|
if (startsWith(str, 'file://')) {
|
|
str = str.substring(7)
|
|
|
|
// Absolute path.
|
|
if (str.charAt(0) === '/') {
|
|
return runOnWindows() ? str.substring(1) : str
|
|
}
|
|
}
|
|
|
|
return str
|
|
}
|
|
|
|
function getUriFromSystemPath (path) {
|
|
if (path.startsWith('file://')) {
|
|
return path
|
|
}
|
|
|
|
if (runOnWindows()) {
|
|
return 'file://' + (/^\w:/.exec(path) ? '/' : '') + path
|
|
}
|
|
|
|
return 'file://' + path
|
|
}
|
|
|
|
// -----------------------------------------------------------------------------
|
|
|
|
// Returns the top (root) parent of one object.
|
|
function getTopParent (object, useFakeParent) {
|
|
function _getTopParent (object, useFakeParent) {
|
|
return (useFakeParent && object.$parent) || object.parent
|
|
}
|
|
|
|
var parent = _getTopParent(object, useFakeParent)
|
|
var p
|
|
while ((p = _getTopParent(parent, useFakeParent)) != null) {
|
|
parent = p
|
|
}
|
|
|
|
return parent
|
|
}
|
|
|
|
|
|
// -----------------------------------------------------------------------------
|
|
|
|
// Check that an item is descendant of another one
|
|
function isDescendant(child, parent) {
|
|
var current = child.parent
|
|
while (current) {
|
|
if (current === parent)
|
|
return true
|
|
current = current.parent
|
|
}
|
|
return false
|
|
}
|
|
|
|
// -----------------------------------------------------------------------------
|
|
|
|
// Retrieve first focussable item of an Item. If no item found, return undefined
|
|
function getFirstFocussableItemInItem(item) {
|
|
var next = item.nextItemInFocusChain();
|
|
if (next && isDescendant(next, item)){
|
|
return next;
|
|
}
|
|
return undefined;
|
|
}
|
|
|
|
// Retrieve last focussable item of an Item. If no item found, return undefined
|
|
function getLastFocussableItemInItem(item) {
|
|
var next = item.nextItemInFocusChain();
|
|
if(next && !isDescendant(next, item)){
|
|
return undefined;
|
|
}
|
|
var current
|
|
do{
|
|
current = next;
|
|
next = current.nextItemInFocusChain();
|
|
} while(isDescendant(next, item) && next.visible)
|
|
return current;
|
|
}
|
|
|
|
// -----------------------------------------------------------------------------
|
|
|
|
// Load by default a window in the ui/views folder.
|
|
// If options.isString is equals to true, a marshalling component can
|
|
// be used.
|
|
//
|
|
// Supported options: isString, exitHandler, properties.
|
|
//
|
|
// If exitHandler is used, window must implement exitStatus signal.
|
|
function openWindow (window, parent, options, fullscreen) {
|
|
var object = createObject(window, parent, options)
|
|
|
|
object.closing.connect(object.destroy.bind(object))
|
|
|
|
if (options && options.exitHandler) {
|
|
object.exitStatus.connect(
|
|
// Bind to access parent properties.
|
|
options.exitHandler.bind(parent)
|
|
)
|
|
}
|
|
if( runOnWindows()){
|
|
object.show() // Needed for Windows : Show the window in all case. Allow to graphically locate the window before going to fullscreen.
|
|
if(fullscreen)
|
|
object.showFullScreen()// Should be equivalent to changing visibility
|
|
}else if(fullscreen)
|
|
object.showFullScreen()// Should be equivalent to changing visibility
|
|
else
|
|
object.show()
|
|
return object
|
|
}
|
|
|
|
// -----------------------------------------------------------------------------
|
|
|
|
function resolveImageUri (name) {
|
|
return name
|
|
//? 'image://internal/' + removeScheme(Qt.resolvedUrl('/assets/images/' + name + '.svg'))
|
|
? 'image://internal/' + name
|
|
: ''
|
|
}
|
|
|
|
// -----------------------------------------------------------------------------
|
|
|
|
|
|
function runOnWindows () {
|
|
var os = Qt.platform.os
|
|
return os === 'windows' || os === 'winrt'
|
|
}
|
|
|
|
// -----------------------------------------------------------------------------
|
|
|
|
// Test if a point is in a item.
|
|
//
|
|
// `source` is the item that generated the point.
|
|
// `target` is the item to test.
|
|
// `point` is the point to test.
|
|
function pointIsInItem (source, target, point) {
|
|
point = source.mapToItem(target.parent, point.x, point.y)
|
|
|
|
return (
|
|
point.x >= target.x &&
|
|
point.y >= target.y &&
|
|
point.x < target.x + target.width &&
|
|
point.y < target.y + target.height
|
|
)
|
|
}
|
|
|
|
// -----------------------------------------------------------------------------
|
|
|
|
// Test the type of a qml object.
|
|
// Warning: this function is probably not portable
|
|
// on new versions of Qt.
|
|
//
|
|
// So, if you want to use it on a specific `className`, please to add
|
|
// a test in `test_qmlTypeof_data` of `utils.spec.qml`.
|
|
function qmlTypeof (object, className) {
|
|
var str = object.toString()
|
|
|
|
return (
|
|
str.indexOf(className + '(') == 0 ||
|
|
str.indexOf(className + '_QML') == 0
|
|
)
|
|
}
|
|
|
|
// -----------------------------------------------------------------------------
|
|
|
|
function removeScheme (url) {
|
|
return url.toString().replace(SCHEME_REGEX, '')
|
|
}
|
|
|
|
// -----------------------------------------------------------------------------
|
|
|
|
// A copy of `Window.setTimeout` from js.
|
|
// delay is in milliseconds.
|
|
function setTimeout (parent, delay, cb) {
|
|
var timer = new (function (parent) {
|
|
return Qt.createQmlObject('import QtQml 2.2; Timer { }', parent)
|
|
})(parent)
|
|
|
|
timer.interval = delay
|
|
timer.repeat = false
|
|
timer.triggered.connect(cb)
|
|
timer.start()
|
|
|
|
return timer
|
|
}
|
|
|
|
// =============================================================================
|
|
// GENERIC.
|
|
// =============================================================================
|
|
|
|
function _computeOptimizedCb (func, context) {
|
|
return context
|
|
? (function () {
|
|
return func.apply(context, arguments)
|
|
}) : func
|
|
}
|
|
|
|
function _indexFinder (array, cb, context) {
|
|
var length = array.length
|
|
|
|
for (var i = 0; i < length; i++) {
|
|
if (cb( (array.getAt ? array.getAt(i) : array[i]), i, array)) {
|
|
return i
|
|
}
|
|
}
|
|
|
|
return -1
|
|
}
|
|
|
|
function _keyFinder (obj, cb, context) {
|
|
var keys = Object.keys(obj)
|
|
var length = keys.length
|
|
|
|
for (var i = 0; i < length; i++) {
|
|
var key = keys[i]
|
|
if (cb(obj[key], key, obj)) {
|
|
return key
|
|
}
|
|
}
|
|
}
|
|
|
|
// -----------------------------------------------------------------------------
|
|
|
|
// Basic assert function.
|
|
function assert (condition, message) {
|
|
if (!condition) {
|
|
throw new Error('Assert: ' + message)
|
|
}
|
|
}
|
|
|
|
// -----------------------------------------------------------------------------
|
|
|
|
function basename (str) {
|
|
if (!str) {
|
|
return ''
|
|
}
|
|
|
|
if (runOnWindows()) {
|
|
str = str.replace(/\\/g, '/')
|
|
}
|
|
|
|
var str2 = str
|
|
var length = str2.length - 1
|
|
|
|
if (str2[length] === '/') {
|
|
str2 = str2.substring(0, length)
|
|
}
|
|
|
|
return str2.slice(str2.lastIndexOf('/') + 1)
|
|
}
|
|
|
|
// -----------------------------------------------------------------------------
|
|
|
|
function capitalizeFirstLetter (str) {
|
|
return str.charAt(0).toUpperCase() + str.slice(1)
|
|
}
|
|
|
|
// -----------------------------------------------------------------------------
|
|
|
|
function dirname (str) {
|
|
if (!str) {
|
|
return ''
|
|
}
|
|
|
|
if (runOnWindows()) {
|
|
str = str.replace(/\\/g, '/')
|
|
}
|
|
|
|
var str2 = str
|
|
var length = str2.length - 1
|
|
|
|
if (str2[length] === '/') {
|
|
str2 = str2.substring(0, length)
|
|
}
|
|
|
|
return str2.slice(0, str2.lastIndexOf('/') + 1)
|
|
}
|
|
|
|
// -----------------------------------------------------------------------------
|
|
|
|
function extractProperties (obj, pattern) {
|
|
if (!pattern) {
|
|
return {}
|
|
}
|
|
|
|
var obj2 = {}
|
|
pattern.forEach(function (property) {
|
|
obj2[property] = obj[property]
|
|
})
|
|
|
|
return obj2
|
|
}
|
|
|
|
// -----------------------------------------------------------------------------
|
|
|
|
// Returns an array from an `object` or `array` argument.
|
|
function ensureArray (obj) {
|
|
if (isArray(obj)) {
|
|
return obj
|
|
}
|
|
|
|
var keys = Object.keys(obj)
|
|
var length = keys.length
|
|
var values = Array(length)
|
|
|
|
for (var i = 0; i < length; i++) {
|
|
values[i] = obj[keys[i]]
|
|
}
|
|
|
|
return values
|
|
}
|
|
|
|
// -----------------------------------------------------------------------------
|
|
|
|
function escapeQuotes (str) {
|
|
return str != null
|
|
? str.replace(/([^'\\]*(?:\\.[^'\\]*)*)'/g, '$1\\\'')
|
|
: ''
|
|
}
|
|
|
|
function decode(str){
|
|
return decodeURIComponent(escape(str.replace(/%([0-9A-Fa-f]{2})/g, function() {
|
|
return String.fromCharCode(parseInt(arguments[1], 16));
|
|
})));
|
|
}
|
|
// -----------------------------------------------------------------------------
|
|
|
|
// Get the first matching value in a array or object.
|
|
// The matching value is obtained if `cb` returns true.
|
|
function find (obj, cb, context) {
|
|
cb = _computeOptimizedCb(cb, context)
|
|
|
|
var finder = isArray(obj) ? _indexFinder : _keyFinder
|
|
var key = finder(obj, cb, context)
|
|
|
|
return key != null && key !== -1 ? obj[key] : null
|
|
}
|
|
|
|
// -----------------------------------------------------------------------------
|
|
|
|
function findIndex (array, cb, context) {
|
|
cb = _computeOptimizedCb(cb, context)
|
|
|
|
var key = _indexFinder(array, cb, context)
|
|
return key != null ? key : -1
|
|
}
|
|
|
|
// -----------------------------------------------------------------------------
|
|
function formatElapsedTime (seconds) {
|
|
seconds = parseInt(seconds, 10)
|
|
//s, m, h, d, W, M, Y
|
|
//1, 60, 3600, 86400, 604800, 2592000, 31104000
|
|
var y = Math.floor(seconds / 31104000)
|
|
if(y > 0)
|
|
return y+ ' years'
|
|
var M = Math.floor(seconds / 2592000)
|
|
if(M > 0)
|
|
return M+' months'
|
|
var w = Math.floor(seconds / 604800)
|
|
if(w>0)
|
|
return w+' week';
|
|
var d = Math.floor(seconds / 86400)
|
|
if(d>0)
|
|
return d+' days'
|
|
var h = Math.floor(seconds / 3600)
|
|
var m = Math.floor((seconds - h * 3600) / 60)
|
|
var s = seconds - h * 3600 - m * 60
|
|
|
|
if (h < 10 && h > 0) {
|
|
h = '0' + h
|
|
}
|
|
|
|
if (m < 10) {
|
|
m = '0' + m
|
|
}
|
|
|
|
if (s < 10) {
|
|
s = '0' + s
|
|
}
|
|
|
|
return (h === 0 ? '' : h + ':') + m + ':' + s
|
|
}
|
|
|
|
function formatDuration (seconds) {
|
|
seconds = parseInt(seconds, 10)
|
|
//s, m, h, d, W, M, Y
|
|
//1, 60, 3600, 86400, 604800, 2592000, 31104000
|
|
var y = Math.floor(seconds / 31104000)
|
|
if(y > 0)
|
|
//: '%1 year'
|
|
return qsTr('formatYears', '', y).arg(y)
|
|
var M = Math.floor(seconds / 2592000)
|
|
if(M > 0)
|
|
//: '%1 month'
|
|
return qsTr('formatMonths', '', M).arg(M)
|
|
var w = Math.floor(seconds / 604800)
|
|
if(w>0)
|
|
//: '%1 week'
|
|
return qsTr('formatWeeks', '', w).arg(w)
|
|
var d = Math.floor(seconds / 86400)
|
|
if(d>0)
|
|
//: '%1 day'
|
|
return qsTr('formatDays', '', d).arg(d)
|
|
var h = Math.floor(seconds / 3600)
|
|
var m = Math.floor((seconds - h * 3600) / 60)
|
|
var s = seconds - h * 3600 - m * 60
|
|
|
|
//: '%1 hour'
|
|
return (h > 0 ? qsTr('formatHours', '', h).arg(h): '')
|
|
//: '%1 minute'
|
|
+ (m > 0 ? (h > 0 ? ', ' : '') +qsTr('formatMinutes', '', m).arg(m): '')
|
|
//: '%1 second'
|
|
+ (s > 0 ? (h> 0 || m > 0 ? ', ' : '') +qsTr('formatSeconds', '', s).arg(s): '')
|
|
}
|
|
|
|
function buildDate(date, time){
|
|
var dateTime = new Date()
|
|
dateTime.setFullYear(date.getFullYear(), date.getMonth(), date.getDate())
|
|
dateTime.setHours(time.getHours())
|
|
dateTime.setMinutes(time.getMinutes())
|
|
dateTime.setSeconds(time.getSeconds())
|
|
return dateTime
|
|
}
|
|
|
|
function equalDate(date1, date2){
|
|
return date1.getFullYear() == date2.getFullYear() && date1.getMonth() == date2.getMonth() && date1.getDate() == date2.getDate()
|
|
}
|
|
|
|
function fromUTC(date){
|
|
return new Date(Date.UTC(date.getUTCFullYear(), date.getUTCMonth(),
|
|
date.getUTCDate(), date.getUTCHours(),
|
|
date.getUTCMinutes(), date.getUTCSeconds()));
|
|
}
|
|
// -----------------------------------------------------------------------------
|
|
|
|
function formatSize (size) {
|
|
var units = ['KB', 'MB', 'GB', 'TB']
|
|
var unit = 'B'
|
|
|
|
if (size == null) {
|
|
size = 0
|
|
}
|
|
|
|
var length = units.length
|
|
for (var i = 0; size >= 1024 && i < length; i++) {
|
|
unit = units[i]
|
|
size /= 1024
|
|
}
|
|
|
|
return parseFloat(size.toFixed(2)) + unit
|
|
}
|
|
|
|
// -----------------------------------------------------------------------------
|
|
|
|
// Generate a random number in the [min, max[ interval.
|
|
// Uniform distrib.
|
|
function genRandomNumber (min, max) {
|
|
return Math.random() * (max - min) + min
|
|
}
|
|
|
|
function genRandomColor(){
|
|
return '#'+ Math.floor(Math.random()*255).toString(16)
|
|
+Math.floor(Math.random()*255).toString(16)
|
|
+Math.floor(Math.random()*255).toString(16)
|
|
}
|
|
|
|
// -----------------------------------------------------------------------------
|
|
|
|
// Generate a random number between a set of intervals.
|
|
// The `intervals` param must be orderer like this:
|
|
// `[ [ 1, 4 ], [ 8, 16 ], [ 22, 25 ] ]`
|
|
function genRandomNumberBetweenIntervals (intervals) {
|
|
if (intervals.length === 1) {
|
|
return genRandomNumber(intervals[0][0], intervals[0][1])
|
|
}
|
|
|
|
// Compute the intervals size.
|
|
var size = 0
|
|
intervals.forEach(function (interval) {
|
|
size += interval[1] - interval[0]
|
|
})
|
|
|
|
// Generate a value in the interval: `[0, size[`
|
|
var n = genRandomNumber(0, size)
|
|
|
|
// Map the value in the right interval.
|
|
n += intervals[0][0]
|
|
for (var i = 0; i < intervals.length - 1; i++) {
|
|
if (n < intervals[i][1]) {
|
|
break
|
|
}
|
|
|
|
n += intervals[i + 1][0] - intervals[i][1]
|
|
}
|
|
|
|
return n
|
|
}
|
|
|
|
// -----------------------------------------------------------------------------
|
|
|
|
// Returns the extension of a filename.
|
|
function getExtension (str) {
|
|
var index = str.lastIndexOf('.')
|
|
|
|
if (index === -1) {
|
|
return ''
|
|
}
|
|
|
|
return str.slice(index + 1)
|
|
}
|
|
|
|
// -----------------------------------------------------------------------------
|
|
|
|
// Test if a value is included in an array or object.
|
|
function includes (obj, value, startIndex) {
|
|
obj = ensureArray(obj)
|
|
if (startIndex == null) {
|
|
startIndex = 0
|
|
}
|
|
var length = obj.length
|
|
|
|
for (var i = startIndex; i < length; i++) {
|
|
if (
|
|
value == obj[i] ||
|
|
// Check `NaN`.
|
|
(value !== value && obj[i] !== obj[i])
|
|
) {
|
|
return true
|
|
}
|
|
}
|
|
return false
|
|
}
|
|
|
|
// -----------------------------------------------------------------------------
|
|
|
|
function isArray (array) {
|
|
return (array instanceof Array)
|
|
}
|
|
|
|
// -----------------------------------------------------------------------------
|
|
|
|
function isFunction (func) {
|
|
return typeof func === 'function'
|
|
}
|
|
|
|
// -----------------------------------------------------------------------------
|
|
|
|
function isInteger (integer) {
|
|
return integer === parseInt(integer, 10)
|
|
}
|
|
|
|
// -----------------------------------------------------------------------------
|
|
|
|
function isObject (object) {
|
|
return object !== null && typeof object === 'object'
|
|
}
|
|
|
|
// -----------------------------------------------------------------------------
|
|
|
|
function isString (string) {
|
|
return typeof string === 'string' || string instanceof String
|
|
}
|
|
|
|
// -----------------------------------------------------------------------------
|
|
|
|
// Convert a snake_case string to a lowerCamelCase string.
|
|
function snakeToCamel (s) {
|
|
return s.replace(/(\_\w)/g, function (matches) {
|
|
return matches[1].toUpperCase()
|
|
})
|
|
}
|
|
|
|
// -----------------------------------------------------------------------------
|
|
|
|
// Test if a string starts by a given string.
|
|
function startsWith (str, searchStr) {
|
|
if (searchStr == null) {
|
|
searchStr = ''
|
|
}
|
|
|
|
return str.slice(0, searchStr.length) === searchStr
|
|
}
|
|
|
|
// -----------------------------------------------------------------------------
|
|
|
|
// Invoke a `cb` function with each value of the interval: `[0, n[`.
|
|
// Return a mapped array created with the returned values of `cb`.
|
|
function times (n, cb, context) {
|
|
var arr = Array(Math.max(0, n))
|
|
cb = _computeOptimizedCb(cb, context, 1)
|
|
|
|
for (var i = 0; i < n; i++) {
|
|
arr[i] = cb(i)
|
|
}
|
|
|
|
return arr
|
|
}
|
|
|
|
// -----------------------------------------------------------------------------
|
|
|
|
function unscapeHtml (str) {
|
|
return str.replace(/&/g, '&')
|
|
.replace(/</g, '\u2063<')
|
|
.replace(/>/g, '\u2063>')
|
|
.replace(/"/g, '"')
|
|
.replace(/'/g, ''')
|
|
}
|
|
|
|
// -----------------------------------------------------------------------------
|
|
|
|
function write (fileName, text) {
|
|
// TODO: Deal with async.
|
|
var request = new XMLHttpRequest()
|
|
request.open('PUT', getUriFromSystemPath(fileName), false)
|
|
request.send(text)
|
|
}
|
|
|
|
function computeAvatarSize (container, maxSize, ratio) {
|
|
var height = container.height * ratio
|
|
var width = container.width * ratio
|
|
var size = height < maxSize && height > 0 ? height : maxSize
|
|
return size < width ? size : width
|
|
}
|
|
|
|
// -----------------------------------------------------------------------------
|
|
|
|
function openCodecOnlineInstallerDialog (mainWindow, coreObject, cancelCallBack, successCallBack, errorCallBack) {
|
|
mainWindow.showConfirmationLambdaPopup("",
|
|
//: "Installation de codec"
|
|
qsTr("codec_install"),
|
|
//: "Télécharger le codec %1 (%2) ?"
|
|
qsTr("download_codec").arg(capitalizeFirstLetter(coreObject.mimeType)).arg(coreObject.encoderDescription),
|
|
function (confirmed) {
|
|
if (confirmed) {
|
|
coreObject.loaded.connect(function(success) {
|
|
mainWindow.closeLoadingPopup()
|
|
if (success) {
|
|
//: "Succès"
|
|
mainWindow.showInformationPopup(qsTr("information_popup_success_title"),
|
|
//: "Le codec a été installé avec succès."
|
|
qsTr("information_popup_codec_install_success_text"), true)
|
|
if (successCallBack)
|
|
successCallBack()
|
|
} else {
|
|
mainWindow.showInformationPopup(qsTr("information_popup_error_title"),
|
|
//: "Le codec n'a pas pu être installé."
|
|
qsTr("information_popup_codec_install_error_text"), false)
|
|
if (errorCallBack)
|
|
errorCallBack()
|
|
}
|
|
})
|
|
coreObject.extractError.connect(function() {
|
|
mainWindow.closeLoadingPopup()
|
|
mainWindow.showInformationPopup(qsTr("information_popup_error_title"),
|
|
//: "Le codec n'a pas pu être sauvegardé."
|
|
qsTr("information_popup_codec_save_error_text"), false)
|
|
if (errorCallBack)
|
|
errorCallBack()
|
|
})
|
|
coreObject.downloadError.connect(function() {
|
|
mainWindow.closeLoadingPopup()
|
|
mainWindow.showInformationPopup(qsTr("information_popup_error_title"),
|
|
//: "Le codec n'a pas pu être téléchargé."
|
|
qsTr("information_popup_codec_download_error_text"), false)
|
|
if (errorCallBack)
|
|
errorCallBack()
|
|
})
|
|
|
|
//: "Téléchargement en cours …"
|
|
mainWindow.showLoadingPopup(qsTr("loading_popup_codec_install_progress"))
|
|
coreObject.downloadAndExtract()
|
|
} else
|
|
if (cancelCallBack)
|
|
cancelCallBack()
|
|
}
|
|
)
|
|
}
|
|
|
|
function printObject(o) {
|
|
var out = '';
|
|
for (var p in o) {
|
|
out += p + ': ' + o[p] + '\n';
|
|
}
|
|
if(!o)
|
|
return 'Empty'
|
|
else
|
|
return out;
|
|
}
|
|
|
|
function equalObject(a, b) {
|
|
var countA = 0, countB = 0;
|
|
if(a == b) return true // operator could be performed
|
|
for (var i in a) {// Check for all members
|
|
if(a[i] != b[i]) return false
|
|
else ++countA
|
|
}
|
|
for (var j in b) {// Check count
|
|
++countB
|
|
}
|
|
return countB == countA && countA > 0 // if count=0; then the first '==' should already worked
|
|
}
|
|
|
|
function infoDialog(window, message) {
|
|
window.attachVirtualWindow(buildCommonDialogUri('ConfirmDialog'), {
|
|
buttonTexts : ['',qsTr('okButton')],
|
|
descriptionText: message,
|
|
showButtonOnly: 1
|
|
}, function (status) {})
|
|
}
|
|
|
|
// Set position of list.currentItem into the scrollItem
|
|
function updatePosition(scrollItem, list){
|
|
if(scrollItem.height == 0) return;
|
|
var item = list.itemAtIndex(list.currentIndex)
|
|
var centerItemPos = 0
|
|
var topItemPos = 0
|
|
var bottomItemPos = 0
|
|
if(!item) item = list.currentItem
|
|
if( item && (list.expanded || list.expanded == undefined)){
|
|
// For debugging just in case
|
|
//var listPosition = item.mapToItem(favoriteList, item.x, item.y)
|
|
//var newPosition = favoriteList.mapToItem(mainItem, listPosition.x, listPosition.y)
|
|
//console.log("item pos: " +item.x + " / " +item.y)
|
|
//console.log("fav pos: " +favoriteList.x + " / " +favoriteList.y)
|
|
//console.log("fav content: " +favoriteList.contentX + " / " +favoriteList.contentY)
|
|
//console.log("main pos: " +mainItem.x + " / " +mainItem.y)
|
|
//console.log("main content: " +mainItem.contentX + " / " +mainItem.contentY)
|
|
//console.log("list pos: " +listPosition.x + " / " +listPosition.y)
|
|
//console.log("new pos: " +newPosition.x + " / " +newPosition.y)
|
|
//console.log("header pos: " +headerItem.x + " / " +headerItem.y)
|
|
//console.log("Moving to " + (headerItem.y+item.y))
|
|
// Middle position
|
|
//centerItemPos = item.y + list.y + item.height/2
|
|
//if( list.headerHeight) centerItemPos += list.headerHeight
|
|
topItemPos = item.y
|
|
if( list != scrollItem) topItemPos += list.y
|
|
if( list.headerHeight) topItemPos += list.headerHeight
|
|
bottomItemPos = topItemPos +item.height
|
|
}
|
|
if(item){
|
|
// Middle position
|
|
//var centerPos = centerItemPos - scrollItem.height/2
|
|
//scrollItem.contentY = Math.max(0, Math.min(centerPos, scrollItem.height, scrollItem.contentHeight-scrollItem.height))
|
|
// Visible position
|
|
if( topItemPos < scrollItem.contentY){
|
|
// Display item at the beginning
|
|
scrollItem.contentY = topItemPos
|
|
//console.debug("Set to top", scrollItem.contentY,topItemPos, item.height)
|
|
}else if(bottomItemPos > scrollItem.contentY + scrollItem.height){
|
|
// Display item at the end
|
|
scrollItem.contentY = bottomItemPos - scrollItem.height
|
|
//console.debug("Set to bottom",scrollItem.contentY,list.y,list.headerHeight, topItemPos, bottomItemPos, scrollItem.height, bottomItemPos - scrollItem.height, item.height)
|
|
}else{
|
|
//console.debug("Inside, do not move", topItemPos, bottomItemPos, scrollItem.contentY, (scrollItem.contentY + scrollItem.height))
|
|
}
|
|
|
|
}else{
|
|
// console.debug("Item is null")
|
|
}
|
|
}
|
|
|
|
// Transform svg file to unicode emoji
|
|
function codepointFromFilename(filename) {
|
|
let baseName = filename.split('.')[0];
|
|
let parts = baseName.replace(/_/g, '-').split('-');
|
|
let codePoints = parts.map(hex => parseInt(hex, 16));
|
|
var unicode = String.fromCodePoint(...codePoints);
|
|
return unicode;
|
|
}
|
|
|
|
|
|
// -----------------------------------------------------------------------------
|
|
|
|
function getSizeWithScreenRatio(size){
|
|
if (size == 0) {
|
|
return size;
|
|
}
|
|
return size > 0
|
|
? Math.max(Math.round(size * Linphone.DefaultStyle.dp), 1)
|
|
: Math.min(Math.round(size * Linphone.DefaultStyle.dp), -1);
|
|
} |