commit 1f91576a0bf33c9d632595cf433d547d1f1d1e06 Author: Sébastien Blin Date: Mon Aug 3 13:27:42 2020 -0400 client-qml: add initial commit Change-Id: I32bfdd2a618aa7ac6181da2697e241667b010aab diff --git a/.clang-format b/.clang-format new file mode 100644 index 00000000..8a799fd7 --- /dev/null +++ b/.clang-format @@ -0,0 +1,101 @@ +Language: Cpp +AccessModifierOffset: -4 +AlignAfterOpenBracket: Align +AlignConsecutiveAssignments: false +AlignConsecutiveDeclarations: false +AlignEscapedNewlines: DontAlign +AlignOperands: true +AlignTrailingComments: true +AllowAllParametersOfDeclarationOnNextLine: true +AllowShortBlocksOnASingleLine: false +AllowShortCaseLabelsOnASingleLine: false +AllowShortFunctionsOnASingleLine: Inline +AllowShortIfStatementsOnASingleLine: false +AllowShortLoopsOnASingleLine: false +AlwaysBreakAfterReturnType: None +AlwaysBreakBeforeMultilineStrings: false +AlwaysBreakTemplateDeclarations: true +AlwaysBreakAfterDefinitionReturnType: All +BinPackArguments: false +BinPackParameters: false +BraceWrapping: + AfterClass: true + AfterControlStatement: false + AfterEnum: false + AfterFunction: true + AfterNamespace: false + AfterObjCDeclaration: false + AfterStruct: true + AfterUnion: false + BeforeCatch: false + BeforeElse: false + IndentBraces: false + SplitEmptyFunction: false + SplitEmptyRecord: false + SplitEmptyNamespace: false +BreakBeforeBinaryOperators: All +BreakBeforeBraces: Custom +BreakBeforeInheritanceComma: false +BreakBeforeTernaryOperators: true +BreakConstructorInitializersBeforeComma: false +BreakConstructorInitializers: BeforeComma +BreakAfterJavaFieldAnnotations: false +BreakStringLiterals: true +ColumnLimit: 100 +CommentPragmas: '^ IWYU pragma:' +CompactNamespaces: false +ConstructorInitializerAllOnOneLineOrOnePerLine: false +ConstructorInitializerIndentWidth: 4 +ContinuationIndentWidth: 4 +Cpp11BracedListStyle: true +DerivePointerAlignment: false +DisableFormat: false +ExperimentalAutoDetectBinPacking: false +FixNamespaceComments: true +ForEachMacros: + - forever # avoids { wrapped to next line + - foreach + - Q_FOREACH + - BOOST_FOREACH +IncludeCategories: + - Regex: '^.ts +source_file = translations/ring_client_windows.ts +source_lang = en +type = TS diff --git a/JamiInstaller/.gitignore b/JamiInstaller/.gitignore new file mode 100644 index 00000000..26814d3f --- /dev/null +++ b/JamiInstaller/.gitignore @@ -0,0 +1,3 @@ +/obj +/bin +Components.wxs diff --git a/JamiInstaller/Config.wxi b/JamiInstaller/Config.wxi new file mode 100644 index 00000000..f24ee3ff --- /dev/null +++ b/JamiInstaller/Config.wxi @@ -0,0 +1,19 @@ + + + + + + + + + + + + + + + + + + + diff --git a/JamiInstaller/HarvestFilter.xslt b/JamiInstaller/HarvestFilter.xslt new file mode 100644 index 00000000..b9179f47 --- /dev/null +++ b/JamiInstaller/HarvestFilter.xslt @@ -0,0 +1,44 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/JamiInstaller/JamiInstaller.wax b/JamiInstaller/JamiInstaller.wax new file mode 100644 index 00000000..a3b03657 --- /dev/null +++ b/JamiInstaller/JamiInstaller.wax @@ -0,0 +1,9 @@ + + + + + + false + true + false + \ No newline at end of file diff --git a/JamiInstaller/JamiInstaller.wixproj b/JamiInstaller/JamiInstaller.wixproj new file mode 100644 index 00000000..9c64ca6e --- /dev/null +++ b/JamiInstaller/JamiInstaller.wixproj @@ -0,0 +1,70 @@ + + + + Debug + x64 + 3.10 + dbbfbc55-1c20-4d21-ae3b-6e8b14c4fe48 + 2.0 + jami.release.$(Platform) + jami.beta.$(Platform) + Package + JamiInstaller + x64 + + + bin\$(Configuration)\ + obj\$(Configuration)\ + HarvestPath=..\x64\Release + True + + + + + + + bin\$(Configuration)\ + obj\$(Configuration)\ + HarvestPath=..\x64\Beta + True + + + + + + + + + + + + + + + + + + + + $(WixExtDir)\WixUtilExtension.dll + WixUtilExtension + + + $(WixExtDir)\WixUIExtension.dll + WixUIExtension + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/JamiInstaller/Localization.wxl b/JamiInstaller/Localization.wxl new file mode 100644 index 00000000..a649d175 --- /dev/null +++ b/JamiInstaller/Localization.wxl @@ -0,0 +1,7 @@ + + + By installing this software you agree to the terms in the license agreement + + + diff --git a/JamiInstaller/Product.wxs b/JamiInstaller/Product.wxs new file mode 100644 index 00000000..fe6a02bd --- /dev/null +++ b/JamiInstaller/Product.wxs @@ -0,0 +1,135 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + APPLICATIONFOLDER="" + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 1 + 1 + 1 + 1 + 1 + + + WIXUI_EXITDIALOGOPTIONALCHECKBOX = 1 and NOT Installed + + + NOT AbortInstall = 1 + + + + + + + WIXNONUILAUNCH + + + + + + + + + + + + + + + + + + + diff --git a/JamiInstaller/StandardComponents.wxs b/JamiInstaller/StandardComponents.wxs new file mode 100644 index 00000000..85847159 --- /dev/null +++ b/JamiInstaller/StandardComponents.wxs @@ -0,0 +1,86 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/JamiInstaller/main-banner.bmp b/JamiInstaller/main-banner.bmp new file mode 100644 index 00000000..a5e88425 Binary files /dev/null and b/JamiInstaller/main-banner.bmp differ diff --git a/JamiInstaller/top-banner.bmp b/JamiInstaller/top-banner.bmp new file mode 100644 index 00000000..c7efb6fc Binary files /dev/null and b/JamiInstaller/top-banner.bmp differ diff --git a/License.rtf b/License.rtf new file mode 100644 index 00000000..fecb01cc --- /dev/null +++ b/License.rtf @@ -0,0 +1,869 @@ +{\rtf1\adeflang1025\ansi\ansicpg1252\uc1\adeff0\deff0\stshfdbch31505\stshfloch31506\stshfhich31506\stshfbi0\deflang4105\deflangfe2052\themelang4105\themelangfe0\themelangcs0{\fonttbl{\f0\fbidi \froman\fcharset0\fprq2{\*\panose 02020603050405020304}Times New Roman;}{\f34\fbidi \froman\fcharset0\fprq2{\*\panose 02040503050406030204}Cambria Math;} +{\flomajor\f31500\fbidi \froman\fcharset0\fprq2{\*\panose 02020603050405020304}Times New Roman;}{\fdbmajor\f31501\fbidi \froman\fcharset0\fprq2{\*\panose 02020603050405020304}Times New Roman;} +{\fhimajor\f31502\fbidi \fswiss\fcharset0\fprq2{\*\panose 020f0302020204030204}Calibri Light;}{\fbimajor\f31503\fbidi \froman\fcharset0\fprq2{\*\panose 02020603050405020304}Times New Roman;} +{\flominor\f31504\fbidi \froman\fcharset0\fprq2{\*\panose 02020603050405020304}Times New Roman;}{\fdbminor\f31505\fbidi \froman\fcharset0\fprq2{\*\panose 02020603050405020304}Times New Roman;} +{\fhiminor\f31506\fbidi \fswiss\fcharset0\fprq2{\*\panose 020f0502020204030204}Calibri;}{\fbiminor\f31507\fbidi \froman\fcharset0\fprq2{\*\panose 02020603050405020304}Times New Roman;}{\f420\fbidi \froman\fcharset238\fprq2 Times New Roman CE;} +{\f421\fbidi \froman\fcharset204\fprq2 Times New Roman Cyr;}{\f423\fbidi \froman\fcharset161\fprq2 Times New Roman Greek;}{\f424\fbidi \froman\fcharset162\fprq2 Times New Roman Tur;}{\f425\fbidi \froman\fcharset177\fprq2 Times New Roman (Hebrew);} +{\f426\fbidi \froman\fcharset178\fprq2 Times New Roman (Arabic);}{\f427\fbidi \froman\fcharset186\fprq2 Times New Roman Baltic;}{\f428\fbidi \froman\fcharset163\fprq2 Times New Roman (Vietnamese);}{\f760\fbidi \froman\fcharset238\fprq2 Cambria Math CE;} +{\f761\fbidi \froman\fcharset204\fprq2 Cambria Math Cyr;}{\f763\fbidi \froman\fcharset161\fprq2 Cambria Math Greek;}{\f764\fbidi \froman\fcharset162\fprq2 Cambria Math Tur;}{\f767\fbidi \froman\fcharset186\fprq2 Cambria Math Baltic;} +{\f768\fbidi \froman\fcharset163\fprq2 Cambria Math (Vietnamese);}{\flomajor\f31508\fbidi \froman\fcharset238\fprq2 Times New Roman CE;}{\flomajor\f31509\fbidi \froman\fcharset204\fprq2 Times New Roman Cyr;} +{\flomajor\f31511\fbidi \froman\fcharset161\fprq2 Times New Roman Greek;}{\flomajor\f31512\fbidi \froman\fcharset162\fprq2 Times New Roman Tur;}{\flomajor\f31513\fbidi \froman\fcharset177\fprq2 Times New Roman (Hebrew);} +{\flomajor\f31514\fbidi \froman\fcharset178\fprq2 Times New Roman (Arabic);}{\flomajor\f31515\fbidi \froman\fcharset186\fprq2 Times New Roman Baltic;}{\flomajor\f31516\fbidi \froman\fcharset163\fprq2 Times New Roman (Vietnamese);} +{\fdbmajor\f31518\fbidi \froman\fcharset238\fprq2 Times New Roman CE;}{\fdbmajor\f31519\fbidi \froman\fcharset204\fprq2 Times New Roman Cyr;}{\fdbmajor\f31521\fbidi \froman\fcharset161\fprq2 Times New Roman Greek;} +{\fdbmajor\f31522\fbidi \froman\fcharset162\fprq2 Times New Roman Tur;}{\fdbmajor\f31523\fbidi \froman\fcharset177\fprq2 Times New Roman (Hebrew);}{\fdbmajor\f31524\fbidi \froman\fcharset178\fprq2 Times New Roman (Arabic);} +{\fdbmajor\f31525\fbidi \froman\fcharset186\fprq2 Times New Roman Baltic;}{\fdbmajor\f31526\fbidi \froman\fcharset163\fprq2 Times New Roman (Vietnamese);}{\fhimajor\f31528\fbidi \fswiss\fcharset238\fprq2 Calibri Light CE;} +{\fhimajor\f31529\fbidi \fswiss\fcharset204\fprq2 Calibri Light Cyr;}{\fhimajor\f31531\fbidi \fswiss\fcharset161\fprq2 Calibri Light Greek;}{\fhimajor\f31532\fbidi \fswiss\fcharset162\fprq2 Calibri Light Tur;} +{\fhimajor\f31535\fbidi \fswiss\fcharset186\fprq2 Calibri Light Baltic;}{\fbimajor\f31538\fbidi \froman\fcharset238\fprq2 Times New Roman CE;}{\fbimajor\f31539\fbidi \froman\fcharset204\fprq2 Times New Roman Cyr;} +{\fbimajor\f31541\fbidi \froman\fcharset161\fprq2 Times New Roman Greek;}{\fbimajor\f31542\fbidi \froman\fcharset162\fprq2 Times New Roman Tur;}{\fbimajor\f31543\fbidi \froman\fcharset177\fprq2 Times New Roman (Hebrew);} +{\fbimajor\f31544\fbidi \froman\fcharset178\fprq2 Times New Roman (Arabic);}{\fbimajor\f31545\fbidi \froman\fcharset186\fprq2 Times New Roman Baltic;}{\fbimajor\f31546\fbidi \froman\fcharset163\fprq2 Times New Roman (Vietnamese);} +{\flominor\f31548\fbidi \froman\fcharset238\fprq2 Times New Roman CE;}{\flominor\f31549\fbidi \froman\fcharset204\fprq2 Times New Roman Cyr;}{\flominor\f31551\fbidi \froman\fcharset161\fprq2 Times New Roman Greek;} +{\flominor\f31552\fbidi \froman\fcharset162\fprq2 Times New Roman Tur;}{\flominor\f31553\fbidi \froman\fcharset177\fprq2 Times New Roman (Hebrew);}{\flominor\f31554\fbidi \froman\fcharset178\fprq2 Times New Roman (Arabic);} +{\flominor\f31555\fbidi \froman\fcharset186\fprq2 Times New Roman Baltic;}{\flominor\f31556\fbidi \froman\fcharset163\fprq2 Times New Roman (Vietnamese);}{\fdbminor\f31558\fbidi \froman\fcharset238\fprq2 Times New Roman CE;} +{\fdbminor\f31559\fbidi \froman\fcharset204\fprq2 Times New Roman Cyr;}{\fdbminor\f31561\fbidi \froman\fcharset161\fprq2 Times New Roman Greek;}{\fdbminor\f31562\fbidi \froman\fcharset162\fprq2 Times New Roman Tur;} +{\fdbminor\f31563\fbidi \froman\fcharset177\fprq2 Times New Roman (Hebrew);}{\fdbminor\f31564\fbidi \froman\fcharset178\fprq2 Times New Roman (Arabic);}{\fdbminor\f31565\fbidi \froman\fcharset186\fprq2 Times New Roman Baltic;} +{\fdbminor\f31566\fbidi \froman\fcharset163\fprq2 Times New Roman (Vietnamese);}{\fhiminor\f31568\fbidi \fswiss\fcharset238\fprq2 Calibri CE;}{\fhiminor\f31569\fbidi \fswiss\fcharset204\fprq2 Calibri Cyr;} +{\fhiminor\f31571\fbidi \fswiss\fcharset161\fprq2 Calibri Greek;}{\fhiminor\f31572\fbidi \fswiss\fcharset162\fprq2 Calibri Tur;}{\fhiminor\f31575\fbidi \fswiss\fcharset186\fprq2 Calibri Baltic;} +{\fhiminor\f31576\fbidi \fswiss\fcharset163\fprq2 Calibri (Vietnamese);}{\fbiminor\f31578\fbidi \froman\fcharset238\fprq2 Times New Roman CE;}{\fbiminor\f31579\fbidi \froman\fcharset204\fprq2 Times New Roman Cyr;} +{\fbiminor\f31581\fbidi \froman\fcharset161\fprq2 Times New Roman Greek;}{\fbiminor\f31582\fbidi \froman\fcharset162\fprq2 Times New Roman Tur;}{\fbiminor\f31583\fbidi \froman\fcharset177\fprq2 Times New Roman (Hebrew);} +{\fbiminor\f31584\fbidi \froman\fcharset178\fprq2 Times New Roman (Arabic);}{\fbiminor\f31585\fbidi \froman\fcharset186\fprq2 Times New Roman Baltic;}{\fbiminor\f31586\fbidi \froman\fcharset163\fprq2 Times New Roman (Vietnamese);}} +{\colortbl;\red0\green0\blue0;\red0\green0\blue255;\red0\green255\blue255;\red0\green255\blue0;\red255\green0\blue255;\red255\green0\blue0;\red255\green255\blue0;\red255\green255\blue255;\red0\green0\blue128;\red0\green128\blue128;\red0\green128\blue0; +\red128\green0\blue128;\red128\green0\blue0;\red128\green128\blue0;\red128\green128\blue128;\red192\green192\blue192;\red0\green0\blue0;\red0\green0\blue0;}{\*\defchp \fs22\loch\af31506\hich\af31506\dbch\af31505 }{\*\defpap +\ql \li0\ri0\sa160\sl259\slmult1\widctlpar\wrapdefault\aspalpha\aspnum\faauto\adjustright\rin0\lin0\itap0 }\noqfpromote {\stylesheet{\ql \li0\ri0\sa160\sl259\slmult1\widctlpar\wrapdefault\aspalpha\aspnum\faauto\adjustright\rin0\lin0\itap0 \rtlch\fcs1 +\af0\afs22\alang1025 \ltrch\fcs0 \fs22\lang4105\langfe2052\loch\f31506\hich\af31506\dbch\af31505\cgrid\langnp4105\langfenp2052 \snext0 \sqformat \spriority0 Normal;}{\*\cs10 \additive \ssemihidden \sunhideused \spriority1 Default Paragraph Font;}{\* +\ts11\tsrowd\trftsWidthB3\trpaddl108\trpaddr108\trpaddfl3\trpaddft3\trpaddfb3\trpaddfr3\trcbpat1\trcfpat1\tblind0\tblindtype3\tsvertalt\tsbrdrt\tsbrdrl\tsbrdrb\tsbrdrr\tsbrdrdgl\tsbrdrdgr\tsbrdrh\tsbrdrv \ql \li0\ri0\sa160\sl259\slmult1 +\widctlpar\wrapdefault\aspalpha\aspnum\faauto\adjustright\rin0\lin0\itap0 \rtlch\fcs1 \af0\afs22\alang1025 \ltrch\fcs0 \fs22\lang4105\langfe2052\loch\f31506\hich\af31506\dbch\af31505\cgrid\langnp4105\langfenp2052 \snext11 \ssemihidden \sunhideused +Normal Table;}{\s15\qc \li0\ri0\sb240\sa60\sl259\slmult1\widctlpar\wrapdefault\aspalpha\aspnum\faauto\outlinelevel0\adjustright\rin0\lin0\itap0 \rtlch\fcs1 \ab\af31503\afs32\alang1025 \ltrch\fcs0 +\b\fs32\lang4105\langfe2052\kerning28\loch\f31502\hich\af31502\dbch\af31501\cgrid\langnp4105\langfenp2052 \sbasedon0 \snext0 \slink16 \sqformat \spriority10 \styrsid15664314 Title;}{\*\cs16 \additive \rtlch\fcs1 \ab\af31503\afs32 \ltrch\fcs0 +\b\fs32\kerning28\loch\f31502\hich\af31502\dbch\af31501 \sbasedon10 \slink15 \slocked \spriority10 \styrsid15664314 Title Char;}}{\*\rsidtbl \rsid350521\rsid1073743\rsid4589873\rsid9323379\rsid10056905\rsid14959562\rsid15664314\rsid16088643\rsid16389575} +{\mmathPr\mmathFont34\mbrkBin0\mbrkBinSub0\msmallFrac0\mdispDef1\mlMargin0\mrMargin0\mdefJc1\mwrapIndent1440\mintLim0\mnaryLim1}{\info{\operator Zhang mingrui}{\creatim\yr2019\mo4\dy23\hr10\min37}{\revtim\yr2019\mo4\dy23\hr11\min15}{\version14}{\edmins11} +{\nofpages28}{\nofwords5147}{\nofchars29338}{\nofcharsws34417}{\vern101}}{\*\xmlnstbl {\xmlns1 http://schemas.microsoft.com/office/word/2003/wordml}}\paperw12240\paperh15840\margl1440\margr1440\margt1440\margb1440\gutter0\ltrsect +\widowctrl\ftnbj\aenddoc\trackmoves0\trackformatting1\donotembedsysfont0\relyonvml0\donotembedlingdata1\grfdocevents0\validatexml0\showplaceholdtext0\ignoremixedcontent0\saveinvalidxml0\showxmlerrors0\horzdoc\dghspace120\dgvspace120\dghorigin1701 +\dgvorigin1984\dghshow0\dgvshow3\jcompress\viewkind1\viewscale100\rsidroot1073743 \fet0{\*\wgrffmtfilter 2450}\ilfomacatclnup0\ltrpar \sectd \ltrsect\linex0\sectdefaultcl\sftnbj {\*\pnseclvl1\pnucrm\pnstart1\pnindent720\pnhang {\pntxta .}}{\*\pnseclvl2 +\pnucltr\pnstart1\pnindent720\pnhang {\pntxta .}}{\*\pnseclvl3\pndec\pnstart1\pnindent720\pnhang {\pntxta .}}{\*\pnseclvl4\pnlcltr\pnstart1\pnindent720\pnhang {\pntxta )}}{\*\pnseclvl5\pndec\pnstart1\pnindent720\pnhang {\pntxtb (}{\pntxta )}}{\*\pnseclvl6 +\pnlcltr\pnstart1\pnindent720\pnhang {\pntxtb (}{\pntxta )}}{\*\pnseclvl7\pnlcrm\pnstart1\pnindent720\pnhang {\pntxtb (}{\pntxta )}}{\*\pnseclvl8\pnlcltr\pnstart1\pnindent720\pnhang {\pntxtb (}{\pntxta )}}{\*\pnseclvl9\pnlcrm\pnstart1\pnindent720\pnhang +{\pntxtb (}{\pntxta )}}\pard\plain \ltrpar\ql \li0\ri0\sa160\sl259\slmult1\widctlpar\wrapdefault\aspalpha\aspnum\faauto\adjustright\rin0\lin0\itap0\pararsid4589873 \rtlch\fcs1 \af0\afs22\alang1025 \ltrch\fcs0 +\fs22\lang4105\langfe2052\loch\af31506\hich\af31506\dbch\af31505\cgrid\langnp4105\langfenp2052 {\rtlch\fcs1 \af31501\afs18 \ltrch\fcs0 \f31501\fs18\lang1033\langfe2052\langnp1033\insrsid16389575\charrsid16088643 \hich\af31501\dbch\af31505\loch\f31501 +GNU GENERAL PUBLIC LICENSE}{\rtlch\fcs1 \af31501\afs18 \ltrch\fcs0 \f31501\fs18\lang1033\langfe2052\langnp1033\insrsid15664314\charrsid16088643 +\par }{\rtlch\fcs1 \af31501\afs18 \ltrch\fcs0 \f31501\fs18\lang1033\langfe2052\langnp1033\insrsid16389575\charrsid16088643 \hich\af31501\dbch\af31505\loch\f31501 Version 3, 29 June 2007}{\rtlch\fcs1 \af31501\afs18 \ltrch\fcs0 +\f31501\fs18\lang1033\langfe2052\langnp1033\insrsid4589873\charrsid16088643 +\par }{\rtlch\fcs1 \af31501\afs18 \ltrch\fcs0 \f31501\fs18\lang1033\langfe2052\langnp1033\insrsid16389575\charrsid16088643 \hich\af31501\dbch\af31505\loch\f31501 Copyright (C) 2007 Free Software Foundation, Inc. +\par \hich\af31501\dbch\af31505\loch\f31501 Everyone is permitted to copy and distribute verbatim copies +\par \hich\af31501\dbch\af31505\loch\f31501 of this license document, but changing it is not allowed. +\par }{\rtlch\fcs1 \af31501\afs18 \ltrch\fcs0 \f31501\fs18\lang1033\langfe2052\langnp1033\insrsid4589873\charrsid16088643 +\par }{\rtlch\fcs1 \af31501\afs18 \ltrch\fcs0 \f31501\fs18\lang1033\langfe2052\langnp1033\insrsid16389575\charrsid16088643 \hich\af31501\dbch\af31505\loch\f31501 Preamble +\par +\par \hich\af31501\dbch\af31505\loch\f31501 The GNU General Public License is a free, copyleft license\hich\af31501\dbch\af31505\loch\f31501 for +\par \hich\af31501\dbch\af31505\loch\f31501 software and other kinds of works. +\par +\par \hich\af31501\dbch\af31505\loch\f31501 The licenses for most software and other practical works are designed +\par \hich\af31501\dbch\af31505\loch\f31501 to take away your freedom to share and change the works. By contrast, +\par \hich\af31501\dbch\af31505\loch\f31501 the GNU General Public License is intended to guarantee your freedom to +\par \hich\af31501\dbch\af31505\loch\f31501 sh\hich\af31501\dbch\af31505\loch\f31501 are and change all versions of a program--to make sure it remains free +\par \hich\af31501\dbch\af31505\loch\f31501 software for all its users. We, the Free Software Foundation, use the +\par \hich\af31501\dbch\af31505\loch\f31501 GNU General Public License for most of our software; it applies also to +\par \hich\af31501\dbch\af31505\loch\f31501 any other work released this way by its au\hich\af31501\dbch\af31505\loch\f31501 thors. You can apply it to +\par \hich\af31501\dbch\af31505\loch\f31501 your programs, too. +\par +\par \hich\af31501\dbch\af31505\loch\f31501 When we speak of free software, we are referring to freedom, not +\par \hich\af31501\dbch\af31505\loch\f31501 price. Our General Public Licenses are designed to make sure that you +\par \hich\af31501\dbch\af31505\loch\f31501 have the freedom to distribute copies of free software (and charge for +\par \hich\af31501\dbch\af31505\loch\f31501 them if you wish), that you receive source code or can get it if you +\par \hich\af31501\dbch\af31505\loch\f31501 want it, that you can change the software or use pieces of it in new +\par \hich\af31501\dbch\af31505\loch\f31501 free programs, and that you know you can do these things. +\par +\par \hich\af31501\dbch\af31505\loch\f31501 To protect your rights, we need to prevent others from denying you +\par \hich\af31501\dbch\af31505\loch\f31501 these rights or asking you to surrender the rights. Therefore, you have +\par \hich\af31501\dbch\af31505\loch\f31501 certain responsibilities if you distribute copies of the software, or if +\par \hich\af31501\dbch\af31505\loch\f31501 you modify it: responsibilities to respect \hich\af31501\dbch\af31505\loch\f31501 the freedom of others. +\par +\par \hich\af31501\dbch\af31505\loch\f31501 For example, if you distribute copies of such a program, whether +\par \hich\af31501\dbch\af31505\loch\f31501 gratis or for a fee, you must pass on to the recipients the same +\par \hich\af31501\dbch\af31505\loch\f31501 freedoms that you received. You must make sure that they, too, receive +\par \hich\af31501\dbch\af31505\loch\f31501 or can get the source code. A\hich\af31501\dbch\af31505\loch\f31501 nd you must show them these terms so they +\par \hich\af31501\dbch\af31505\loch\f31501 know their rights. +\par +\par \hich\af31501\dbch\af31505\loch\f31501 Developers that use the GNU GPL protect your rights with two steps: +\par \hich\af31501\dbch\af31505\loch\f31501 (1) assert copyright on the software, and (2) offer you this License +\par \hich\af31501\dbch\af31505\loch\f31501 giving you legal permission to copy, distribute and/or mo\hich\af31501\dbch\af31505\loch\f31501 dify it. +\par +\par \hich\af31501\dbch\af31505\loch\f31501 For the developers' and authors' protection, the GPL clearly explains +\par \hich\af31501\dbch\af31505\loch\f31501 that there is no warranty for this free software. For both users' and +\par \hich\af31501\dbch\af31505\loch\f31501 authors' sake, the GPL requires that modified versions be marked as +\par \hich\af31501\dbch\af31505\loch\f31501 changed, so that their problems will \hich\af31501\dbch\af31505\loch\f31501 not be attributed erroneously to +\par \hich\af31501\dbch\af31505\loch\f31501 authors of previous versions. +\par +\par \hich\af31501\dbch\af31505\loch\f31501 Some devices are designed to deny users access to install or run +\par \hich\af31501\dbch\af31505\loch\f31501 modified versions of the software inside them, although the manufacturer +\par \hich\af31501\dbch\af31505\loch\f31501 can do so. This is fundamentally incompatible with the aim of +\par \hich\af31501\dbch\af31505\loch\f31501 protecting users' freedom to change the software. The systematic +\par \hich\af31501\dbch\af31505\loch\f31501 pattern of such abuse occurs in the area of products for individuals to +\par \hich\af31501\dbch\af31505\loch\f31501 use, which is precisely where it is most unacceptable. \hich\af31501\dbch\af31505\loch\f31501 Therefore, we +\par \hich\af31501\dbch\af31505\loch\f31501 have designed this version of the GPL to prohibit the practice for those +\par \hich\af31501\dbch\af31505\loch\f31501 products. If such problems arise substantially in other domains, we +\par \hich\af31501\dbch\af31505\loch\f31501 stand ready to extend this provision to those domains in future versions +\par \hich\af31501\dbch\af31505\loch\f31501 of the GPL, as needed to p\hich\af31501\dbch\af31505\loch\f31501 rotect the freedom of users. +\par +\par \hich\af31501\dbch\af31505\loch\f31501 Finally, every program is threatened constantly by software patents. +\par \hich\af31501\dbch\af31505\loch\f31501 States should not allow patents to restrict development and use of +\par \hich\af31501\dbch\af31505\loch\f31501 software on general-purpose computers, but in those that do, we wish to +\par \hich\af31501\dbch\af31505\loch\f31501 avoid the special \hich\af31501\dbch\af31505\loch\f31501 danger that patents applied to a free program could +\par \hich\af31501\dbch\af31505\loch\f31501 make it effectively proprietary. To prevent this, the GPL assures that +\par \hich\af31501\dbch\af31505\loch\f31501 patents cannot be used to render the program non-free. +\par +\par \hich\af31501\dbch\af31505\loch\f31501 The precise terms and conditions for copying, distribution and +\par \hich\af31501\dbch\af31505\loch\f31501 modification \hich\af31501\dbch\af31505\loch\f31501 follow. +\par +\par \hich\af31501\dbch\af31505\loch\f31501 TERMS AND CONDITIONS +\par +\par \hich\af31501\dbch\af31505\loch\f31501 0. Definitions. +\par +\par \hich\af31501\dbch\af31505\loch\f31501 "This License" refers to version 3 of the GNU General Public License. +\par +\par \hich\af31501\dbch\af31505\loch\f31501 "Copyright" also means copyright-like laws that apply to other kinds of +\par \hich\af31501\dbch\af31505\loch\f31501 works, such as semiconductor masks. +\par +\par \hich\af31501\dbch\af31505\loch\f31501 "The Program" refers to any copyrightable work licensed under this +\par \hich\af31501\dbch\af31505\loch\f31501 License. Each licensee is addressed as "you". "Licensees" and +\par \hich\af31501\dbch\af31505\loch\f31501 "recipients" may\hich\af31501\dbch\af31505\loch\f31501 be individuals or organizations. +\par +\par \hich\af31501\dbch\af31505\loch\f31501 To "modify" a work means to copy from or adapt all or part of the work +\par \hich\af31501\dbch\af31505\loch\f31501 in a fashion requiring copyright permission, other than the making of an +\par \hich\af31501\dbch\af31505\loch\f31501 exact copy. The resulting work is called a "modified version" of the +\par \hich\af31501\dbch\af31505\loch\f31501 earlier\hich\af31501\dbch\af31505\loch\f31501 work or a work "based on" the earlier work. +\par +\par \hich\af31501\dbch\af31505\loch\f31501 A "covered work" means either the unmodified Program or a work based +\par \hich\af31501\dbch\af31505\loch\f31501 on the Program. +\par +\par \hich\af31501\dbch\af31505\loch\f31501 To "propagate" a work means to do anything with it that, without +\par \hich\af31501\dbch\af31505\loch\f31501 permission, would make you directly or secondarily liable f\hich\af31501\dbch\af31505\loch\f31501 or +\par \hich\af31501\dbch\af31505\loch\f31501 infringement under applicable copyright law, except executing it on a +\par \hich\af31501\dbch\af31505\loch\f31501 computer or modifying a private copy. Propagation includes copying, +\par \hich\af31501\dbch\af31505\loch\f31501 distribution (with or without modification), making available to the +\par \hich\af31501\dbch\af31505\loch\f31501 public, and in some countries other activitie\hich\af31501\dbch\af31505\loch\f31501 s as well. +\par +\par \hich\af31501\dbch\af31505\loch\f31501 To "convey" a work means any kind of propagation that enables other +\par \hich\af31501\dbch\af31505\loch\f31501 parties to make or receive copies. Mere interaction with a user through +\par \hich\af31501\dbch\af31505\loch\f31501 a computer network, with no transfer of a copy, is not conveying. +\par +\par \hich\af31501\dbch\af31505\loch\f31501 An interactive user interface displays "Appropriate Legal Notices" +\par \hich\af31501\dbch\af31505\loch\f31501 to the extent that it includes a convenient and prominently visible +\par \hich\af31501\dbch\af31505\loch\f31501 feature that (1) displays an appropriate copyright notice, and (2) +\par \hich\af31501\dbch\af31505\loch\f31501 tells the user that there is no warranty for the work \hich\af31501\dbch\af31505\loch\f31501 (except to the +\par \hich\af31501\dbch\af31505\loch\f31501 extent that warranties are provided), that licensees may convey the +\par \hich\af31501\dbch\af31505\loch\f31501 work under this License, and how to view a copy of this License. If +\par \hich\af31501\dbch\af31505\loch\f31501 the interface presents a list of user commands or options, such as a +\par \hich\af31501\dbch\af31505\loch\f31501 menu, a prominent item in the list \hich\af31501\dbch\af31505\loch\f31501 meets this criterion. +\par +\par \hich\af31501\dbch\af31505\loch\f31501 1. Source Code. +\par +\par \hich\af31501\dbch\af31505\loch\f31501 The "source code" for a work means the preferred form of the work +\par \hich\af31501\dbch\af31505\loch\f31501 for making modifications to it. "Object code" means any non-source +\par \hich\af31501\dbch\af31505\loch\f31501 form of a work. +\par +\par \hich\af31501\dbch\af31505\loch\f31501 A "Standard Interface" means an interface that either is an offic\hich\af31501\dbch\af31505\loch\f31501 ial +\par \hich\af31501\dbch\af31505\loch\f31501 standard defined by a recognized standards body, or, in the case of +\par \hich\af31501\dbch\af31505\loch\f31501 interfaces specified for a particular programming language, one that +\par \hich\af31501\dbch\af31505\loch\f31501 is widely used among developers working in that language. +\par +\par \hich\af31501\dbch\af31505\loch\f31501 The "System Libraries" of an executable work include any\hich\af31501\dbch\af31505\loch\f31501 thing, other +\par \hich\af31501\dbch\af31505\loch\f31501 than the work as a whole, that (a) is included in the normal form of +\par \hich\af31501\dbch\af31505\loch\f31501 packaging a Major Component, but which is not part of that Major +\par \hich\af31501\dbch\af31505\loch\f31501 Component, and (b) serves only to enable use of the work with that +\par \hich\af31501\dbch\af31505\loch\f31501 Major Component, or to implement a Standard Interface for which an +\par \hich\af31501\dbch\af31505\loch\f31501 implementation is available to the public in source code form. A +\par \hich\af31501\dbch\af31505\loch\f31501 "Major Component", in this context, means a major essential component +\par \hich\af31501\dbch\af31505\loch\f31501 (kernel, window system, and so on) of the specific op\hich\af31501\dbch\af31505\loch\f31501 erating system +\par \hich\af31501\dbch\af31505\loch\f31501 (if any) on which the executable work runs, or a compiler used to +\par \hich\af31501\dbch\af31505\loch\f31501 produce the work, or an object code interpreter used to run it. +\par +\par \hich\af31501\dbch\af31505\loch\f31501 The "Corresponding Source" for a work in object code form means all +\par \hich\af31501\dbch\af31505\loch\f31501 the source code needed to generate, instal\hich\af31501\dbch\af31505\loch\f31501 l, and (for an executable +\par \hich\af31501\dbch\af31505\loch\f31501 work) run the object code and to modify the work, including scripts to +\par \hich\af31501\dbch\af31505\loch\f31501 control those activities. However, it does not include the work's +\par \hich\af31501\dbch\af31505\loch\f31501 System Libraries, or general-purpose tools or generally available free +\par \hich\af31501\dbch\af31505\loch\f31501 programs which are us\hich\af31501\dbch\af31505\loch\f31501 ed unmodified in performing those activities but +\par \hich\af31501\dbch\af31505\loch\f31501 which are not part of the work. For example, Corresponding Source +\par \hich\af31501\dbch\af31505\loch\f31501 includes interface definition files associated with source files for +\par \hich\af31501\dbch\af31505\loch\f31501 the work, and the source code for shared libraries and dynamically +\par \hich\af31501\dbch\af31505\loch\f31501 link\hich\af31501\dbch\af31505\loch\f31501 ed subprograms that the work is specifically designed to require, +\par \hich\af31501\dbch\af31505\loch\f31501 such as by intimate data communication or control flow between those +\par \hich\af31501\dbch\af31505\loch\f31501 subprograms and other parts of the work. +\par +\par \hich\af31501\dbch\af31505\loch\f31501 The Corresponding Source need not include anything that users +\par \hich\af31501\dbch\af31505\loch\f31501 can regenerate au\hich\af31501\dbch\af31505\loch\f31501 tomatically from other parts of the Corresponding +\par \hich\af31501\dbch\af31505\loch\f31501 Source. +\par +\par \hich\af31501\dbch\af31505\loch\f31501 The Corresponding Source for a work in source code form is that +\par \hich\af31501\dbch\af31505\loch\f31501 same work. +\par +\par \hich\af31501\dbch\af31505\loch\f31501 2. Basic Permissions. +\par +\par \hich\af31501\dbch\af31505\loch\f31501 All rights granted under this License are granted for the term of +\par \hich\af31501\dbch\af31505\loch\f31501 copyright on the Program, and are irrevocable provided the stated +\par \hich\af31501\dbch\af31505\loch\f31501 conditions are met. This License explicitly affirms your unlimited +\par \hich\af31501\dbch\af31505\loch\f31501 permission to run the unmodified Program. The output fr\hich\af31501\dbch\af31505\loch\f31501 om running a +\par \hich\af31501\dbch\af31505\loch\f31501 covered work is covered by this License only if the output, given its +\par \hich\af31501\dbch\af31505\loch\f31501 content, constitutes a covered work. This License acknowledges your +\par \hich\af31501\dbch\af31505\loch\f31501 rights of fair use or other equivalent, as provided by copyright law. +\par +\par \hich\af31501\dbch\af31505\loch\f31501 You may make, run and propagate c\hich\af31501\dbch\af31505\loch\f31501 overed works that you do not +\par \hich\af31501\dbch\af31505\loch\f31501 convey, without conditions so long as your license otherwise remains +\par \hich\af31501\dbch\af31505\loch\f31501 in force. You may convey covered works to others for the sole purpose +\par \hich\af31501\dbch\af31505\loch\f31501 of having them make modifications exclusively for you, or provide you +\par \hich\af31501\dbch\af31505\loch\f31501 with facilities f\hich\af31501\dbch\af31505\loch\f31501 or running those works, provided that you comply with +\par \hich\af31501\dbch\af31505\loch\f31501 the terms of this License in conveying all material for which you do +\par \hich\af31501\dbch\af31505\loch\f31501 not control copyright. Those thus making or running the covered works +\par \hich\af31501\dbch\af31505\loch\f31501 for you must do so exclusively on your behalf, under your dire\hich\af31501\dbch\af31505\loch\f31501 ction +\par \hich\af31501\dbch\af31505\loch\f31501 and control, on terms that prohibit them from making any copies of +\par \hich\af31501\dbch\af31505\loch\f31501 your copyrighted material outside their relationship with you. +\par +\par \hich\af31501\dbch\af31505\loch\f31501 Conveying under any other circumstances is permitted solely under +\par \hich\af31501\dbch\af31505\loch\f31501 the conditions stated below. Sublicensing is not all\hich\af31501\dbch\af31505\loch\f31501 owed; section 10 +\par \hich\af31501\dbch\af31505\loch\f31501 makes it unnecessary. +\par +\par \hich\af31501\dbch\af31505\loch\f31501 3. Protecting Users' Legal Rights From Anti-Circumvention Law. +\par +\par \hich\af31501\dbch\af31505\loch\f31501 No covered work shall be deemed part of an effective technological +\par \hich\af31501\dbch\af31505\loch\f31501 measure under any applicable law fulfilling obligations under article +\par \hich\af31501\dbch\af31505\loch\f31501 11 of the WIPO copyright treaty adopted on 20 December 1996, or +\par \hich\af31501\dbch\af31505\loch\f31501 similar laws prohibiting or restricting circumvention of such +\par \hich\af31501\dbch\af31505\loch\f31501 measures. +\par +\par \hich\af31501\dbch\af31505\loch\f31501 When you convey a covered work, you waive any leg\hich\af31501\dbch\af31505\loch\f31501 al power to forbid +\par \hich\af31501\dbch\af31505\loch\f31501 circumvention of technological measures to the extent such circumvention +\par \hich\af31501\dbch\af31505\loch\f31501 is effected by exercising rights under this License with respect to +\par \hich\af31501\dbch\af31505\loch\f31501 the covered work, and you disclaim any intention to limit operation or +\par \hich\af31501\dbch\af31505\loch\f31501 modification of the work \hich\af31501\dbch\af31505\loch\f31501 as a means of enforcing, against the work's +\par \hich\af31501\dbch\af31505\loch\f31501 users, your or third parties' legal rights to forbid circumvention of +\par \hich\af31501\dbch\af31505\loch\f31501 technological measures. +\par +\par \hich\af31501\dbch\af31505\loch\f31501 4. Conveying Verbatim Copies. +\par +\par \hich\af31501\dbch\af31505\loch\f31501 You may convey verbatim copies of the Program's source code as you +\par \hich\af31501\dbch\af31505\loch\f31501 receive it, in any \hich\af31501\dbch\af31505\loch\f31501 medium, provided that you conspicuously and +\par \hich\af31501\dbch\af31505\loch\f31501 appropriately publish on each copy an appropriate copyright notice; +\par \hich\af31501\dbch\af31505\loch\f31501 keep intact all notices stating that this License and any +\par \hich\af31501\dbch\af31505\loch\f31501 non-permissive terms added in accord with section 7 apply to the code; +\par \hich\af31501\dbch\af31505\loch\f31501 keep intact all notices of the absence of any warranty; and give all +\par \hich\af31501\dbch\af31505\loch\f31501 recipients a copy of this License along with the Program. +\par +\par \hich\af31501\dbch\af31505\loch\f31501 You may charge any price or no price for each copy that you convey, +\par \hich\af31501\dbch\af31505\loch\f31501 and you may offer support or warranty protection for a fee. +\par +\par \hich\af31501\dbch\af31505\loch\f31501 5. Conveying Modified Source Versions. +\par +\par \hich\af31501\dbch\af31505\loch\f31501 You may convey a work based on the Program, or the modifications to +\par \hich\af31501\dbch\af31505\loch\f31501 produce it from the Program, in the form of source code under the +\par \hich\af31501\dbch\af31505\loch\f31501 terms of section 4, provided that you also meet all of these conditions: +\par +\par \hich\af31501\dbch\af31505\loch\f31501 a) The \hich\af31501\dbch\af31505\loch\f31501 work must carry prominent notices stating that you modified +\par \hich\af31501\dbch\af31505\loch\f31501 it, and giving a relevant date. +\par +\par \hich\af31501\dbch\af31505\loch\f31501 b) The work must carry prominent notices stating that it is +\par \hich\af31501\dbch\af31505\loch\f31501 released under this License and any conditions added under section +\par \hich\af31501\dbch\af31505\loch\f31501 7. This requirement modifies the re\hich\af31501\dbch\af31505\loch\f31501 quirement in section 4 to +\par \hich\af31501\dbch\af31505\loch\f31501 "keep intact all notices". +\par +\par \hich\af31501\dbch\af31505\loch\f31501 c) You must license the entire work, as a whole, under this +\par \hich\af31501\dbch\af31505\loch\f31501 License to anyone who comes into possession of a copy. This +\par \hich\af31501\dbch\af31505\loch\f31501 License will therefore apply, along with any applicable section 7 +\par \hich\af31501\dbch\af31505\loch\f31501 additional term\hich\af31501\dbch\af31505\loch\f31501 s, to the whole of the work, and all its parts, +\par \hich\af31501\dbch\af31505\loch\f31501 regardless of how they are packaged. This License gives no +\par \hich\af31501\dbch\af31505\loch\f31501 permission to license the work in any other way, but it does not +\par \hich\af31501\dbch\af31505\loch\f31501 invalidate such permission if you have separately received it. +\par +\par \hich\af31501\dbch\af31505\loch\f31501 d) If the work has interactive user interfaces, each must display +\par \hich\af31501\dbch\af31505\loch\f31501 Appropriate Legal Notices; however, if the Program has interactive +\par \hich\af31501\dbch\af31505\loch\f31501 interfaces that do not display Appropriate Legal Notices, y\hich\af31501\dbch\af31505\loch\f31501 our +\par \hich\af31501\dbch\af31505\loch\f31501 work need not make them do so. +\par +\par \hich\af31501\dbch\af31505\loch\f31501 A compilation of a covered work with other separate and independent +\par \hich\af31501\dbch\af31505\loch\f31501 works, which are not by their nature extensions of the covered work, +\par \hich\af31501\dbch\af31505\loch\f31501 and which are not combined with it such as to form a larger program, +\par \hich\af31501\dbch\af31505\loch\f31501 in or on a vol\hich\af31501\dbch\af31505\loch\f31501 ume of a storage or distribution medium, is called an +\par \hich\af31501\dbch\af31505\loch\f31501 "aggregate" if the compilation and its resulting copyright are not +\par \hich\af31501\dbch\af31505\loch\f31501 used to limit the access or legal rights of the compilation's users +\par \hich\af31501\dbch\af31505\loch\f31501 beyond what the individual works permit. Inclusion of a covered wo\hich\af31501\dbch\af31505\loch\f31501 rk +\par \hich\af31501\dbch\af31505\loch\f31501 in an aggregate does not cause this License to apply to the other +\par \hich\af31501\dbch\af31505\loch\f31501 parts of the aggregate. +\par +\par \hich\af31501\dbch\af31505\loch\f31501 6. Conveying Non-Source Forms. +\par +\par \hich\af31501\dbch\af31505\loch\f31501 You may convey a covered work in object code form under the terms +\par \hich\af31501\dbch\af31505\loch\f31501 of sections 4 and 5, provided that you also convey the +\par \hich\af31501\dbch\af31505\loch\f31501 machine-r\hich\af31501\dbch\af31505\loch\f31501 eadable Corresponding Source under the terms of this License, +\par \hich\af31501\dbch\af31505\loch\f31501 in one of these ways: +\par +\par \hich\af31501\dbch\af31505\loch\f31501 a) Convey the object code in, or embodied in, a physical product +\par \hich\af31501\dbch\af31505\loch\f31501 (including a physical distribution medium), accompanied by the +\par \hich\af31501\dbch\af31505\loch\f31501 Corresponding Source fixed on a durable physical medium +\par \hich\af31501\dbch\af31505\loch\f31501 customarily used for software interchange. +\par +\par \hich\af31501\dbch\af31505\loch\f31501 b) Convey the object code in, or embodied in, a physical product +\par \hich\af31501\dbch\af31505\loch\f31501 (including a physical distri\hich\af31501\dbch\af31505\loch\f31501 bution medium), accompanied by a +\par \hich\af31501\dbch\af31505\loch\f31501 written offer, valid for at least three years and valid for as +\par \hich\af31501\dbch\af31505\loch\f31501 long as you offer spare parts or customer support for that product +\par \hich\af31501\dbch\af31505\loch\f31501 model, to give anyone who possesses the object code either (1) a +\par \hich\af31501\dbch\af31505\loch\f31501 copy of the Corresponding So\hich\af31501\dbch\af31505\loch\f31501 urce for all the software in the +\par \hich\af31501\dbch\af31505\loch\f31501 product that is covered by this License, on a durable physical +\par \hich\af31501\dbch\af31505\loch\f31501 medium customarily used for software interchange, for a price no +\par \hich\af31501\dbch\af31505\loch\f31501 more than your reasonable cost of physically performing this +\par \hich\af31501\dbch\af31505\loch\f31501 conveying of source, or (2) access\hich\af31501\dbch\af31505\loch\f31501 to copy the +\par \hich\af31501\dbch\af31505\loch\f31501 Corresponding Source from a network server at no charge. +\par +\par \hich\af31501\dbch\af31505\loch\f31501 c) Convey individual copies of the object code with a copy of the +\par \hich\af31501\dbch\af31505\loch\f31501 written offer to provide the Corresponding Source. This +\par \hich\af31501\dbch\af31505\loch\f31501 alternative is allowed only occasionally and noncommercially, \hich\af31501\dbch\af31505\loch\f31501 and +\par \hich\af31501\dbch\af31505\loch\f31501 only if you received the object code with such an offer, in accord +\par \hich\af31501\dbch\af31505\loch\f31501 with subsection 6b. +\par +\par \hich\af31501\dbch\af31505\loch\f31501 d) Convey the object code by offering access from a designated +\par \hich\af31501\dbch\af31505\loch\f31501 place (gratis or for a charge), and offer equivalent access to the +\par \hich\af31501\dbch\af31505\loch\f31501 Corresponding Source in the same way through the same place at no +\par \hich\af31501\dbch\af31505\loch\f31501 further charge. You need not require recipients to copy the +\par \hich\af31501\dbch\af31505\loch\f31501 Corresponding Source along with the object code. If the place to +\par \hich\af31501\dbch\af31505\loch\f31501 copy the object code is a network server, the Corresponding Sou\hich\af31501\dbch\af31505\loch\f31501 rce +\par \hich\af31501\dbch\af31505\loch\f31501 may be on a different server (operated by you or a third party) +\par \hich\af31501\dbch\af31505\loch\f31501 that supports equivalent copying facilities, provided you maintain +\par \hich\af31501\dbch\af31505\loch\f31501 clear directions next to the object code saying where to find the +\par \hich\af31501\dbch\af31505\loch\f31501 Corresponding Source. Regardless of what server hosts \hich\af31501\dbch\af31505\loch\f31501 the +\par \hich\af31501\dbch\af31505\loch\f31501 Corresponding Source, you remain obligated to ensure that it is +\par \hich\af31501\dbch\af31505\loch\f31501 available for as long as needed to satisfy these requirements. +\par +\par \hich\af31501\dbch\af31505\loch\f31501 e) Convey the object code using peer-to-peer transmission, provided +\par \hich\af31501\dbch\af31505\loch\f31501 you inform other peers where the object code and Corresp\hich\af31501\dbch\af31505\loch\f31501 onding +\par \hich\af31501\dbch\af31505\loch\f31501 Source of the work are being offered to the general public at no +\par \hich\af31501\dbch\af31505\loch\f31501 charge under subsection 6d. +\par +\par \hich\af31501\dbch\af31505\loch\f31501 A separable portion of the object code, whose source code is excluded +\par \hich\af31501\dbch\af31505\loch\f31501 from the Corresponding Source as a System Library, need not be +\par \hich\af31501\dbch\af31505\loch\f31501 included in conveying \hich\af31501\dbch\af31505\loch\f31501 the object code work. +\par +\par \hich\af31501\dbch\af31505\loch\f31501 A "User Product" is either (1) a "consumer product", which means any +\par \hich\af31501\dbch\af31505\loch\f31501 tangible personal property which is normally used for personal, family, +\par \hich\af31501\dbch\af31505\loch\f31501 or household purposes, or (2) anything designed or sold for incorporation +\par \hich\af31501\dbch\af31505\loch\f31501 into a dwelling. \hich\af31501\dbch\af31505\loch\f31501 In determining whether a product is a consumer product, +\par \hich\af31501\dbch\af31505\loch\f31501 doubtful cases shall be resolved in favor of coverage. For a particular +\par \hich\af31501\dbch\af31505\loch\f31501 product received by a particular user, "normally used" refers to a +\par \hich\af31501\dbch\af31505\loch\f31501 typical or common use of that class of product, regardless of the status +\par \hich\af31501\dbch\af31505\loch\f31501 of the particular user or of the way in which the particular user +\par \hich\af31501\dbch\af31505\loch\f31501 actually uses, or expects or is expected to use, t\hich\af31501\dbch\af31505\loch\f31501 he product. A product +\par \hich\af31501\dbch\af31505\loch\f31501 is a consumer product regardless of whether the product has substantial +\par \hich\af31501\dbch\af31505\loch\f31501 commercial, industrial or non-consumer uses, unless such uses represent +\par \hich\af31501\dbch\af31505\loch\f31501 the only significant mode of use of the product. +\par +\par \hich\af31501\dbch\af31505\loch\f31501 "Installation Information" for a User P\hich\af31501\dbch\af31505\loch\f31501 roduct means any methods, +\par \hich\af31501\dbch\af31505\loch\f31501 procedures, authorization keys, or other information required to install +\par \hich\af31501\dbch\af31505\loch\f31501 and execute modified versions of a covered work in that User Product from +\par \hich\af31501\dbch\af31505\loch\f31501 a modified version of its Corresponding Source. The information must +\par \hich\af31501\dbch\af31505\loch\f31501 suffice to en\hich\af31501\dbch\af31505\loch\f31501 sure that the continued functioning of the modified object +\par \hich\af31501\dbch\af31505\loch\f31501 code is in no case prevented or interfered with solely because +\par \hich\af31501\dbch\af31505\loch\f31501 modification has been made. +\par +\par \hich\af31501\dbch\af31505\loch\f31501 If you convey an object code work under this section in, or with, or +\par \hich\af31501\dbch\af31505\loch\f31501 specifically for use in, a User Prod\hich\af31501\dbch\af31505\loch\f31501 uct, and the conveying occurs as +\par \hich\af31501\dbch\af31505\loch\f31501 part of a transaction in which the right of possession and use of the +\par \hich\af31501\dbch\af31505\loch\f31501 User Product is transferred to the recipient in perpetuity or for a +\par \hich\af31501\dbch\af31505\loch\f31501 fixed term (regardless of how the transaction is characterized), the +\par \hich\af31501\dbch\af31505\loch\f31501 Corresponding So\hich\af31501\dbch\af31505\loch\f31501 urce conveyed under this section must be accompanied +\par \hich\af31501\dbch\af31505\loch\f31501 by the Installation Information. But this requirement does not apply +\par \hich\af31501\dbch\af31505\loch\f31501 if neither you nor any third party retains the ability to install +\par \hich\af31501\dbch\af31505\loch\f31501 modified object code on the User Product (for example, the work has +\par \hich\af31501\dbch\af31505\loch\f31501 been installed in ROM). +\par +\par \hich\af31501\dbch\af31505\loch\f31501 The requirement to provide Installation Information does not include a +\par \hich\af31501\dbch\af31505\loch\f31501 requirement to continue to provide support service, warranty, or updates +\par \hich\af31501\dbch\af31505\loch\f31501 for a work that has been modified or installed by the recipient, or for +\par \hich\af31501\dbch\af31505\loch\f31501 the User Product in which it has been modified or installed. Access to a +\par \hich\af31501\dbch\af31505\loch\f31501 network may be denied when the modification itself materially and +\par \hich\af31501\dbch\af31505\loch\f31501 adversely affects the operation of the netwo\hich\af31501\dbch\af31505\loch\f31501 rk or violates the rules and +\par \hich\af31501\dbch\af31505\loch\f31501 protocols for communication across the network. +\par +\par \hich\af31501\dbch\af31505\loch\f31501 Corresponding Source conveyed, and Installation Information provided, +\par \hich\af31501\dbch\af31505\loch\f31501 in accord with this section must be in a format that is publicly +\par \hich\af31501\dbch\af31505\loch\f31501 documented (and with an implementation avai\hich\af31501\dbch\af31505\loch\f31501 lable to the public in +\par \hich\af31501\dbch\af31505\loch\f31501 source code form), and must require no special password or key for +\par \hich\af31501\dbch\af31505\loch\f31501 unpacking, reading or copying. +\par +\par \hich\af31501\dbch\af31505\loch\f31501 7. Additional Terms. +\par +\par \hich\af31501\dbch\af31505\loch\f31501 "Additional permissions" are terms that supplement the terms of this +\par \hich\af31501\dbch\af31505\loch\f31501 License by making exceptions from one or mo\hich\af31501\dbch\af31505\loch\f31501 re of its conditions. +\par \hich\af31501\dbch\af31505\loch\f31501 Additional permissions that are applicable to the entire Program shall +\par \hich\af31501\dbch\af31505\loch\f31501 be treated as though they were included in this License, to the extent +\par \hich\af31501\dbch\af31505\loch\f31501 that they are valid under applicable law. If additional permissions +\par \hich\af31501\dbch\af31505\loch\f31501 apply only to part of t\hich\af31501\dbch\af31505\loch\f31501 he Program, that part may be used separately +\par \hich\af31501\dbch\af31505\loch\f31501 under those permissions, but the entire Program remains governed by +\par \hich\af31501\dbch\af31505\loch\f31501 this License without regard to the additional permissions. +\par +\par \hich\af31501\dbch\af31505\loch\f31501 When you convey a copy of a covered work, you may at your option +\par \hich\af31501\dbch\af31505\loch\f31501 remove any additional permissions from that copy, or from any part of +\par \hich\af31501\dbch\af31505\loch\f31501 it. (Additional permissions may be written to require their own +\par \hich\af31501\dbch\af31505\loch\f31501 removal in certain cases when you modify the work.) You\hich\af31501\dbch\af31505\loch\f31501 may place +\par \hich\af31501\dbch\af31505\loch\f31501 additional permissions on material, added by you to a covered work, +\par \hich\af31501\dbch\af31505\loch\f31501 for which you have or can give appropriate copyright permission. +\par +\par \hich\af31501\dbch\af31505\loch\f31501 Notwithstanding any other provision of this License, for material you +\par \hich\af31501\dbch\af31505\loch\f31501 add to a covered work, you may (if author\hich\af31501\dbch\af31505\loch\f31501 ized by the copyright holders of +\par \hich\af31501\dbch\af31505\loch\f31501 that material) supplement the terms of this License with terms: +\par +\par \hich\af31501\dbch\af31505\loch\f31501 a) Disclaiming warranty or limiting liability differently from the +\par \hich\af31501\dbch\af31505\loch\f31501 terms of sections 15 and 16 of this License; or +\par +\par \hich\af31501\dbch\af31505\loch\f31501 b) Requiring preservation of specified rea\hich\af31501\dbch\af31505\loch\f31501 sonable legal notices or +\par \hich\af31501\dbch\af31505\loch\f31501 author attributions in that material or in the Appropriate Legal +\par \hich\af31501\dbch\af31505\loch\f31501 Notices displayed by works containing it; or +\par +\par \hich\af31501\dbch\af31505\loch\f31501 c) Prohibiting misrepresentation of the origin of that material, or +\par \hich\af31501\dbch\af31505\loch\f31501 requiring that modified versions of such material be\hich\af31501\dbch\af31505\loch\f31501 marked in +\par \hich\af31501\dbch\af31505\loch\f31501 reasonable ways as different from the original version; or +\par +\par \hich\af31501\dbch\af31505\loch\f31501 d) Limiting the use for publicity purposes of names of licensors or +\par \hich\af31501\dbch\af31505\loch\f31501 authors of the material; or +\par +\par \hich\af31501\dbch\af31505\loch\f31501 e) Declining to grant rights under trademark law for use of some +\par \hich\af31501\dbch\af31505\loch\f31501 trade names, trademarks, or service marks; or +\par +\par \hich\af31501\dbch\af31505\loch\f31501 f) Requiring indemnification of licensors and authors of that +\par \hich\af31501\dbch\af31505\loch\f31501 material by anyone who conveys the material (or modified versions of +\par \hich\af31501\dbch\af31505\loch\f31501 it) with cont\hich\af31501\dbch\af31505\loch\f31501 ractual assumptions of liability to the recipient, for +\par \hich\af31501\dbch\af31505\loch\f31501 any liability that these contractual assumptions directly impose on +\par \hich\af31501\dbch\af31505\loch\f31501 those licensors and authors. +\par +\par \hich\af31501\dbch\af31505\loch\f31501 All other non-permissive additional terms are considered "further +\par \hich\af31501\dbch\af31505\loch\f31501 restrictions" within the meaning of s\hich\af31501\dbch\af31505\loch\f31501 ection 10. If the Program as you +\par \hich\af31501\dbch\af31505\loch\f31501 received it, or any part of it, contains a notice stating that it is +\par \hich\af31501\dbch\af31505\loch\f31501 governed by this License along with a term that is a further +\par \hich\af31501\dbch\af31505\loch\f31501 restriction, you may remove that term. If a license document contains +\par \hich\af31501\dbch\af31505\loch\f31501 a further restriction\hich\af31501\dbch\af31505\loch\f31501 but permits relicensing or conveying under this +\par \hich\af31501\dbch\af31505\loch\f31501 License, you may add to a covered work material governed by the terms +\par \hich\af31501\dbch\af31505\loch\f31501 of that license document, provided that the further restriction does +\par \hich\af31501\dbch\af31505\loch\f31501 not survive such relicensing or conveying. +\par +\par \hich\af31501\dbch\af31505\loch\f31501 If you add terms to a co\hich\af31501\dbch\af31505\loch\f31501 vered work in accord with this section, you +\par \hich\af31501\dbch\af31505\loch\f31501 must place, in the relevant source files, a statement of the +\par \hich\af31501\dbch\af31505\loch\f31501 additional terms that apply to those files, or a notice indicating +\par \hich\af31501\dbch\af31505\loch\f31501 where to find the applicable terms. +\par +\par \hich\af31501\dbch\af31505\loch\f31501 Additional terms, permissive or non-permissive, may be stated in the +\par \hich\af31501\dbch\af31505\loch\f31501 form of a separately written license, or stated as exceptions; +\par \hich\af31501\dbch\af31505\loch\f31501 the above requirements apply either way. +\par +\par \hich\af31501\dbch\af31505\loch\f31501 8. Termination. +\par +\par \hich\af31501\dbch\af31505\loch\f31501 You may not propagate or modify a covered work except as expressl\hich\af31501\dbch\af31505\loch\f31501 y +\par \hich\af31501\dbch\af31505\loch\f31501 provided under this License. Any attempt otherwise to propagate or +\par \hich\af31501\dbch\af31505\loch\f31501 modify it is void, and will automatically terminate your rights under +\par \hich\af31501\dbch\af31505\loch\f31501 this License (including any patent licenses granted under the third +\par \hich\af31501\dbch\af31505\loch\f31501 paragraph of section 11). +\par +\par \hich\af31501\dbch\af31505\loch\f31501 However, if you cease\hich\af31501\dbch\af31505\loch\f31501 all violation of this License, then your +\par \hich\af31501\dbch\af31505\loch\f31501 license from a particular copyright holder is reinstated (a) +\par \hich\af31501\dbch\af31505\loch\f31501 provisionally, unless and until the copyright holder explicitly and +\par \hich\af31501\dbch\af31505\loch\f31501 finally terminates your license, and (b) permanently, if the copyright +\par \hich\af31501\dbch\af31505\loch\f31501 holder fails t\hich\af31501\dbch\af31505\loch\f31501 o notify you of the violation by some reasonable means +\par \hich\af31501\dbch\af31505\loch\f31501 prior to 60 days after the cessation. +\par +\par \hich\af31501\dbch\af31505\loch\f31501 Moreover, your license from a particular copyright holder is +\par \hich\af31501\dbch\af31505\loch\f31501 reinstated permanently if the copyright holder notifies you of the +\par \hich\af31501\dbch\af31505\loch\f31501 violation by some reasonable means\hich\af31501\dbch\af31505\loch\f31501 , this is the first time you have +\par \hich\af31501\dbch\af31505\loch\f31501 received notice of violation of this License (for any work) from that +\par \hich\af31501\dbch\af31505\loch\f31501 copyright holder, and you cure the violation prior to 30 days after +\par \hich\af31501\dbch\af31505\loch\f31501 your receipt of the notice. +\par +\par \hich\af31501\dbch\af31505\loch\f31501 Termination of your rights under this section does not terminate the +\par \hich\af31501\dbch\af31505\loch\f31501 licenses of parties who have received copies or rights from you under +\par \hich\af31501\dbch\af31505\loch\f31501 this License. If your rights have been terminated and not permanently +\par \hich\af31501\dbch\af31505\loch\f31501 reinstated, you do not qualify to receive new \hich\af31501\dbch\af31505\loch\f31501 licenses for the same +\par \hich\af31501\dbch\af31505\loch\f31501 material under section 10. +\par +\par \hich\af31501\dbch\af31505\loch\f31501 9. Acceptance Not Required for Having Copies. +\par +\par \hich\af31501\dbch\af31505\loch\f31501 You are not required to accept this License in order to receive or +\par \hich\af31501\dbch\af31505\loch\f31501 run a copy of the Program. Ancillary propagation of a covered work +\par \hich\af31501\dbch\af31505\loch\f31501 occurring solely as a co\hich\af31501\dbch\af31505\loch\f31501 nsequence of using peer-to-peer transmission +\par \hich\af31501\dbch\af31505\loch\f31501 to receive a copy likewise does not require acceptance. However, +\par \hich\af31501\dbch\af31505\loch\f31501 nothing other than this License grants you permission to propagate or +\par \hich\af31501\dbch\af31505\loch\f31501 modify any covered work. These actions infringe copyright if you do +\par \hich\af31501\dbch\af31505\loch\f31501 not ac\hich\af31501\dbch\af31505\loch\f31501 cept this License. Therefore, by modifying or propagating a +\par \hich\af31501\dbch\af31505\loch\f31501 covered work, you indicate your acceptance of this License to do so. +\par +\par \hich\af31501\dbch\af31505\loch\f31501 10. Automatic Licensing of Downstream Recipients. +\par +\par \hich\af31501\dbch\af31505\loch\f31501 Each time you convey a covered work, the recipient automatically +\par \hich\af31501\dbch\af31505\loch\f31501 receives \hich\af31501\dbch\af31505\loch\f31501 a license from the original licensors, to run, modify and +\par \hich\af31501\dbch\af31505\loch\f31501 propagate that work, subject to this License. You are not responsible +\par \hich\af31501\dbch\af31505\loch\f31501 for enforcing compliance by third parties with this License. +\par +\par \hich\af31501\dbch\af31505\loch\f31501 An "entity transaction" is a transaction transferring control of an +\par \hich\af31501\dbch\af31505\loch\f31501 organization, or substantially all assets of one, or subdividing an +\par \hich\af31501\dbch\af31505\loch\f31501 organization, or merging organizations. If propagation of a covered +\par \hich\af31501\dbch\af31505\loch\f31501 work results from an entity transaction, each party\hich\af31501\dbch\af31505\loch\f31501 to that +\par \hich\af31501\dbch\af31505\loch\f31501 transaction who receives a copy of the work also receives whatever +\par \hich\af31501\dbch\af31505\loch\f31501 licenses to the work the party's predecessor in interest had or could +\par \hich\af31501\dbch\af31505\loch\f31501 give under the previous paragraph, plus a right to possession of the +\par \hich\af31501\dbch\af31505\loch\f31501 Corresponding Source of the work from the\hich\af31501\dbch\af31505\loch\f31501 predecessor in interest, if +\par \hich\af31501\dbch\af31505\loch\f31501 the predecessor has it or can get it with reasonable efforts. +\par +\par \hich\af31501\dbch\af31505\loch\f31501 You may not impose any further restrictions on the exercise of the +\par \hich\af31501\dbch\af31505\loch\f31501 rights granted or affirmed under this License. For example, you may +\par \hich\af31501\dbch\af31505\loch\f31501 not impose a license fee, ro\hich\af31501\dbch\af31505\loch\f31501 yalty, or other charge for exercise of +\par \hich\af31501\dbch\af31505\loch\f31501 rights granted under this License, and you may not initiate litigation +\par \hich\af31501\dbch\af31505\loch\f31501 (including a cross-claim or counterclaim in a lawsuit) alleging that +\par \hich\af31501\dbch\af31505\loch\f31501 any patent claim is infringed by making, using, selling, offering for +\par \hich\af31501\dbch\af31505\loch\f31501 sale, o\hich\af31501\dbch\af31505\loch\f31501 r importing the Program or any portion of it. +\par +\par \hich\af31501\dbch\af31505\loch\f31501 11. Patents. +\par +\par \hich\af31501\dbch\af31505\loch\f31501 A "contributor" is a copyright holder who authorizes use under this +\par \hich\af31501\dbch\af31505\loch\f31501 License of the Program or a work on which the Program is based. The +\par \hich\af31501\dbch\af31505\loch\f31501 work thus licensed is called the contributor's "contributo\hich\af31501\dbch\af31505\loch\f31501 r version". +\par +\par \hich\af31501\dbch\af31505\loch\f31501 A contributor's "essential patent claims" are all patent claims +\par \hich\af31501\dbch\af31505\loch\f31501 owned or controlled by the contributor, whether already acquired or +\par \hich\af31501\dbch\af31505\loch\f31501 hereafter acquired, that would be infringed by some manner, permitted +\par \hich\af31501\dbch\af31505\loch\f31501 by this License, of making, using, or selling its contributor version, +\par \hich\af31501\dbch\af31505\loch\f31501 but do not include claims that would be infringed only as a +\par \hich\af31501\dbch\af31505\loch\f31501 consequence of further modification of the contributor \hich\af31501\dbch\af31505\loch\f31501 version. For +\par \hich\af31501\dbch\af31505\loch\f31501 purposes of this definition, "control" includes the right to grant +\par \hich\af31501\dbch\af31505\loch\f31501 patent sublicenses in a manner consistent with the requirements of +\par \hich\af31501\dbch\af31505\loch\f31501 this License. +\par +\par \hich\af31501\dbch\af31505\loch\f31501 Each contributor grants you a non-exclusive, worldwide, royalty-free +\par \hich\af31501\dbch\af31505\loch\f31501 patent license under the\hich\af31501\dbch\af31505\loch\f31501 contributor's essential patent claims, to +\par \hich\af31501\dbch\af31505\loch\f31501 make, use, sell, offer for sale, import and otherwise run, modify and +\par \hich\af31501\dbch\af31505\loch\f31501 propagate the contents of its contributor version. +\par +\par \hich\af31501\dbch\af31505\loch\f31501 In the following three paragraphs, a "patent license" is any express +\par \hich\af31501\dbch\af31505\loch\f31501 agreement or commitmen\hich\af31501\dbch\af31505\loch\f31501 t, however denominated, not to enforce a patent +\par \hich\af31501\dbch\af31505\loch\f31501 (such as an express permission to practice a patent or covenant not to +\par \hich\af31501\dbch\af31505\loch\f31501 sue for patent infringement). To "grant" such a patent license to a +\par \hich\af31501\dbch\af31505\loch\f31501 party means to make such an agreement or commitment not to enforce a +\par \hich\af31501\dbch\af31505\loch\f31501 patent against the party. +\par +\par \hich\af31501\dbch\af31505\loch\f31501 If you convey a covered work, knowingly relying on a patent license, +\par \hich\af31501\dbch\af31505\loch\f31501 and the Corresponding Source of the work is not available for anyone +\par \hich\af31501\dbch\af31505\loch\f31501 to copy, free of charge and under the terms of this License, through a +\par \hich\af31501\dbch\af31505\loch\f31501 publicly available network server or other readily accessible means, +\par \hich\af31501\dbch\af31505\loch\f31501 then you must either (1) cause the Corresponding Source to be so +\par \hich\af31501\dbch\af31505\loch\f31501 available, or (2) arrange to deprive yourself of the benefit of the +\par \hich\af31501\dbch\af31505\loch\f31501 patent license for this particular work, or (3) arrang\hich\af31501\dbch\af31505\loch\f31501 e, in a manner +\par \hich\af31501\dbch\af31505\loch\f31501 consistent with the requirements of this License, to extend the patent +\par \hich\af31501\dbch\af31505\loch\f31501 license to downstream recipients. "Knowingly relying" means you have +\par \hich\af31501\dbch\af31505\loch\f31501 actual knowledge that, but for the patent license, your conveying the +\par \hich\af31501\dbch\af31505\loch\f31501 covered work in a country, or \hich\af31501\dbch\af31505\loch\f31501 your recipient's use of the covered work +\par \hich\af31501\dbch\af31505\loch\f31501 in a country, would infringe one or more identifiable patents in that +\par \hich\af31501\dbch\af31505\loch\f31501 country that you have reason to believe are valid. +\par +\par \hich\af31501\dbch\af31505\loch\f31501 If, pursuant to or in connection with a single transaction or +\par \hich\af31501\dbch\af31505\loch\f31501 arrangement, you convey, or pro\hich\af31501\dbch\af31505\loch\f31501 pagate by procuring conveyance of, a +\par \hich\af31501\dbch\af31505\loch\f31501 covered work, and grant a patent license to some of the parties +\par \hich\af31501\dbch\af31505\loch\f31501 receiving the covered work authorizing them to use, propagate, modify +\par \hich\af31501\dbch\af31505\loch\f31501 or convey a specific copy of the covered work, then the patent license +\par \hich\af31501\dbch\af31505\loch\f31501 you grant is a\hich\af31501\dbch\af31505\loch\f31501 utomatically extended to all recipients of the covered +\par \hich\af31501\dbch\af31505\loch\f31501 work and works based on it. +\par +\par \hich\af31501\dbch\af31505\loch\f31501 A patent license is "discriminatory" if it does not include within +\par \hich\af31501\dbch\af31505\loch\f31501 the scope of its coverage, prohibits the exercise of, or is +\par \hich\af31501\dbch\af31505\loch\f31501 conditioned on the non-exercise of one or mor\hich\af31501\dbch\af31505\loch\f31501 e of the rights that are +\par \hich\af31501\dbch\af31505\loch\f31501 specifically granted under this License. You may not convey a covered +\par \hich\af31501\dbch\af31505\loch\f31501 work if you are a party to an arrangement with a third party that is +\par \hich\af31501\dbch\af31505\loch\f31501 in the business of distributing software, under which you make payment +\par \hich\af31501\dbch\af31505\loch\f31501 to the third party based on the extent of your activity of conveying +\par \hich\af31501\dbch\af31505\loch\f31501 the work, and under which the third party grants, to any of the +\par \hich\af31501\dbch\af31505\loch\f31501 parties who would receive the covered work from you, a discriminatory +\par \hich\af31501\dbch\af31505\loch\f31501 patent license (a) in connection with copies of the c\hich\af31501\dbch\af31505\loch\f31501 overed work +\par \hich\af31501\dbch\af31505\loch\f31501 conveyed by you (or copies made from those copies), or (b) primarily +\par \hich\af31501\dbch\af31505\loch\f31501 for and in connection with specific products or compilations that +\par \hich\af31501\dbch\af31505\loch\f31501 contain the covered work, unless you entered into that arrangement, +\par \hich\af31501\dbch\af31505\loch\f31501 or that patent license was granted, prior\hich\af31501\dbch\af31505\loch\f31501 to 28 March 2007. +\par +\par \hich\af31501\dbch\af31505\loch\f31501 Nothing in this License shall be construed as excluding or limiting +\par \hich\af31501\dbch\af31505\loch\f31501 any implied license or other defenses to infringement that may +\par \hich\af31501\dbch\af31505\loch\f31501 otherwise be available to you under applicable patent law. +\par +\par \hich\af31501\dbch\af31505\loch\f31501 12. No Surrender of Others' Freedom. +\par +\par \hich\af31501\dbch\af31505\loch\f31501 If cond\hich\af31501\dbch\af31505\loch\f31501 itions are imposed on you (whether by court order, agreement or +\par \hich\af31501\dbch\af31505\loch\f31501 otherwise) that contradict the conditions of this License, they do not +\par \hich\af31501\dbch\af31505\loch\f31501 excuse you from the conditions of this License. If you cannot convey a +\par \hich\af31501\dbch\af31505\loch\f31501 covered work so as to satisfy simultaneously your\hich\af31501\dbch\af31505\loch\f31501 obligations under this +\par \hich\af31501\dbch\af31505\loch\f31501 License and any other pertinent obligations, then as a consequence you may +\par \hich\af31501\dbch\af31505\loch\f31501 not convey it at all. For example, if you agree to terms that obligate you +\par \hich\af31501\dbch\af31505\loch\f31501 to collect a royalty for further conveying from those to whom you convey +\par \hich\af31501\dbch\af31505\loch\f31501 the Prog\hich\af31501\dbch\af31505\loch\f31501 ram, the only way you could satisfy both those terms and this +\par \hich\af31501\dbch\af31505\loch\f31501 License would be to refrain entirely from conveying the Program. +\par +\par \hich\af31501\dbch\af31505\loch\f31501 13. Use with the GNU Affero General Public License. +\par +\par \hich\af31501\dbch\af31505\loch\f31501 Notwithst\hich\af31501\dbch\af31505\loch\f31501 anding any other provision of this License, you have +\par \hich\af31501\dbch\af31505\loch\f31501 permission to link or combine any covered work with a work licensed +\par \hich\af31501\dbch\af31505\loch\f31501 under version 3 of the GNU Affero General Public License into a single +\par \hich\af31501\dbch\af31505\loch\f31501 combined work, and to convey the resulting work. The terms of t\hich\af31501\dbch\af31505\loch\f31501 his +\par \hich\af31501\dbch\af31505\loch\f31501 License will continue to apply to the part which is the covered work, +\par \hich\af31501\dbch\af31505\loch\f31501 but the special requirements of the GNU Affero General Public License, +\par \hich\af31501\dbch\af31505\loch\f31501 section 13, concerning interaction through a network will apply to the +\par \hich\af31501\dbch\af31505\loch\f31501 combination as such. +\par +\par \hich\af31501\dbch\af31505\loch\f31501 14. Revised Versio\hich\af31501\dbch\af31505\loch\f31501 ns of this License. +\par +\par \hich\af31501\dbch\af31505\loch\f31501 The Free Software Foundation may publish revised and/or new versions of +\par \hich\af31501\dbch\af31505\loch\f31501 the GNU General Public License from time to time. Such new versions will +\par \hich\af31501\dbch\af31505\loch\f31501 be similar in spirit to the present version, but may differ in detail to +\par \hich\af31501\dbch\af31505\loch\f31501 address new prob\hich\af31501\dbch\af31505\loch\f31501 lems or concerns. +\par +\par \hich\af31501\dbch\af31505\loch\f31501 Each version is given a distinguishing version number. If the +\par \hich\af31501\dbch\af31505\loch\f31501 Program specifies that a certain numbered version of the GNU General +\par \hich\af31501\dbch\af31505\loch\f31501 Public License "or any later version" applies to it, you have the +\par \hich\af31501\dbch\af31505\loch\f31501 option of following the terms and condi\hich\af31501\dbch\af31505\loch\f31501 tions either of that numbered +\par \hich\af31501\dbch\af31505\loch\f31501 version or of any later version published by the Free Software +\par \hich\af31501\dbch\af31505\loch\f31501 Foundation. If the Program does not specify a version number of the +\par \hich\af31501\dbch\af31505\loch\f31501 GNU General Public License, you may choose any version ever published +\par \hich\af31501\dbch\af31505\loch\f31501 by the Free Software Foundation. +\par +\par \hich\af31501\dbch\af31505\loch\f31501 If the Program specifies that a proxy can decide which future +\par \hich\af31501\dbch\af31505\loch\f31501 versions of the GNU General Public License can be used, that proxy's +\par \hich\af31501\dbch\af31505\loch\f31501 public statement of acceptance of a version permanently authorizes you +\par \hich\af31501\dbch\af31505\loch\f31501 to choose that versi\hich\af31501\dbch\af31505\loch\f31501 on for the Program. +\par +\par \hich\af31501\dbch\af31505\loch\f31501 Later license versions may give you additional or different +\par \hich\af31501\dbch\af31505\loch\f31501 permissions. However, no additional obligations are imposed on any +\par \hich\af31501\dbch\af31505\loch\f31501 author or copyright holder as a result of your choosing to follow a +\par \hich\af31501\dbch\af31505\loch\f31501 later version. +\par +\par \hich\af31501\dbch\af31505\loch\f31501 15. Disclaimer of Warra\hich\af31501\dbch\af31505\loch\f31501 nty. +\par +\par \hich\af31501\dbch\af31505\loch\f31501 THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY +\par \hich\af31501\dbch\af31505\loch\f31501 APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT +\par \hich\af31501\dbch\af31505\loch\f31501 HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY +\par \hich\af31501\dbch\af31505\loch\f31501 OF ANY KIND, EITHER EXPRESSED OR IMPLIED\hich\af31501\dbch\af31505\loch\f31501 , INCLUDING, BUT NOT LIMITED TO, +\par \hich\af31501\dbch\af31505\loch\f31501 THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +\par \hich\af31501\dbch\af31505\loch\f31501 PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM +\par \hich\af31501\dbch\af31505\loch\f31501 IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF +\par \hich\af31501\dbch\af31505\loch\f31501 ALL \hich\af31501\dbch\af31505\loch\f31501 NECESSARY SERVICING, REPAIR OR CORRECTION. +\par +\par \hich\af31501\dbch\af31505\loch\f31501 16. Limitation of Liability. +\par +\par \hich\af31501\dbch\af31505\loch\f31501 IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +\par \hich\af31501\dbch\af31505\loch\f31501 WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS +\par \hich\af31501\dbch\af31505\loch\f31501 THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY +\par \hich\af31501\dbch\af31505\loch\f31501 GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE +\par \hich\af31501\dbch\af31505\loch\f31501 USE OR INABILITY TO USE THE PROGR\hich\af31501\dbch\af31505\loch\f31501 AM (INCLUDING BUT NOT LIMITED TO LOSS OF +\par \hich\af31501\dbch\af31505\loch\f31501 DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD +\par \hich\af31501\dbch\af31505\loch\f31501 PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), +\par \hich\af31501\dbch\af31505\loch\f31501 EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBIL\hich\af31501\dbch\af31505\loch\f31501 ITY OF +\par \hich\af31501\dbch\af31505\loch\f31501 SUCH DAMAGES. +\par +\par \hich\af31501\dbch\af31505\loch\f31501 17. Interpretation of Sections 15 and 16. +\par +\par \hich\af31501\dbch\af31505\loch\f31501 If the disclaimer of warranty and limitation of liability provided +\par \hich\af31501\dbch\af31505\loch\f31501 above cannot be given local legal effect according to their terms, +\par \hich\af31501\dbch\af31505\loch\f31501 reviewing courts shall apply local law that most closely \hich\af31501\dbch\af31505\loch\f31501 approximates +\par \hich\af31501\dbch\af31505\loch\f31501 an absolute waiver of all civil liability in connection with the +\par \hich\af31501\dbch\af31505\loch\f31501 Program, unless a warranty or assumption of liability accompanies a +\par \hich\af31501\dbch\af31505\loch\f31501 copy of the Program in return for a fee. +\par +\par \hich\af31501\dbch\af31505\loch\f31501 END OF TERMS AND CONDITIONS +\par +\par \hich\af31501\dbch\af31505\loch\f31501 How to Apply These Terms to Your New Pr\hich\af31501\dbch\af31505\loch\f31501 ograms +\par +\par \hich\af31501\dbch\af31505\loch\f31501 If you develop a new program, and you want it to be of the greatest +\par \hich\af31501\dbch\af31505\loch\f31501 possible use to the public, the best way to achieve this is to make it +\par \hich\af31501\dbch\af31505\loch\f31501 free software which everyone can redistribute and change under these terms. +\par +\par \hich\af31501\dbch\af31505\loch\f31501 To do so, attach the following notices to the program. It is safest +\par \hich\af31501\dbch\af31505\loch\f31501 to attach them to the start of each source file to most effectively +\par \hich\af31501\dbch\af31505\loch\f31501 state the exclusion of warranty; and each \hich\af31501\dbch\af31505\loch\f31501 file should have at least +\par \hich\af31501\dbch\af31505\loch\f31501 the "copyright" line and a pointer to where the full notice is found. +\par +\par \hich\af31501\dbch\af31505\loch\f31501 +\par \hich\af31501\dbch\af31505\loch\f31501 Copyright (C) +\par +\par \hich\af31501\dbch\af31505\loch\f31501 This program is free software: you can redistri\hich\af31501\dbch\af31505\loch\f31501 bute it and/or modify +\par \hich\af31501\dbch\af31505\loch\f31501 it under the terms of the GNU General Public License as published by +\par \hich\af31501\dbch\af31505\loch\f31501 the Free Software Foundation, either version 3 of the License, or +\par \hich\af31501\dbch\af31505\loch\f31501 (at your option) any later version. +\par +\par \hich\af31501\dbch\af31505\loch\f31501 This program is distributed in the hope that it will be useful, +\par \hich\af31501\dbch\af31505\loch\f31501 but WITHOUT ANY WARRANTY; without even the implied warranty of +\par \hich\af31501\dbch\af31505\loch\f31501 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +\par \hich\af31501\dbch\af31505\loch\f31501 GNU General Public License for more details. +\par +\par \hich\af31501\dbch\af31505\loch\f31501 You should have received a copy of the GNU General Public License +\par \hich\af31501\dbch\af31505\loch\f31501 along with this p\hich\af31501\dbch\af31505\loch\f31501 rogram. If not, see . +\par +\par \hich\af31501\dbch\af31505\loch\f31501 Also add information on how to contact you by electronic and paper mail. +\par +\par \hich\af31501\dbch\af31505\loch\f31501 If the program does terminal interaction, make it output a short +\par \hich\af31501\dbch\af31505\loch\f31501 notice like this when it starts in an interactive mode: +\par +\par \hich\af31501\dbch\af31505\loch\f31501 Copyright (C) +\par \hich\af31501\dbch\af31505\loch\f31501 This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'. +\par \hich\af31501\dbch\af31505\loch\f31501 This is free software, and you are welcome to redistribute it +\par \hich\af31501\dbch\af31505\loch\f31501 under certai\hich\af31501\dbch\af31505\loch\f31501 n conditions; type `show c' for details. +\par +\par \hich\af31501\dbch\af31505\loch\f31501 The hypothetical commands `show w' and `show c' should show the appropriate +\par \hich\af31501\dbch\af31505\loch\f31501 parts of the General Public License. Of course, your program's commands +\par \hich\af31501\dbch\af31505\loch\f31501 might be different; for a GUI interface, you would use an "about \hich\af31501\dbch\af31505\loch\f31501 box". +\par +\par \hich\af31501\dbch\af31505\loch\f31501 You should also get your employer (if you work as a programmer) or school, +\par \hich\af31501\dbch\af31505\loch\f31501 if any, to sign a "copyright disclaimer" for the program, if necessary. +\par \hich\af31501\dbch\af31505\loch\f31501 For more information on this, and how to apply and follow the GNU GPL, see +\par \hich\af31501\dbch\af31505\loch\f31501 . +\par +\par \hich\af31501\dbch\af31505\loch\f31501 The GNU General Public License does not permit incorporating your program +\par \hich\af31501\dbch\af31505\loch\f31501 into proprietary programs. If your program is a subroutine library, you +\par \hich\af31501\dbch\af31505\loch\f31501 may consider it more useful to permit linking proprietary applications with +\par \hich\af31501\dbch\af31505\loch\f31501 the library. If this is wh\hich\af31501\dbch\af31505\loch\f31501 at you want to do, use the GNU Lesser General +\par \hich\af31501\dbch\af31505\loch\f31501 Public License instead of this License. But first, please read +\par \hich\af31501\dbch\af31505\loch\f31501 . +\par +\par }{\*\themedata 504b030414000600080000002100e9de0fbfff0000001c020000130000005b436f6e74656e745f54797065735d2e786d6cac91cb4ec3301045f748fc83e52d4a +9cb2400825e982c78ec7a27cc0c8992416c9d8b2a755fbf74cd25442a820166c2cd933f79e3be372bd1f07b5c3989ca74aaff2422b24eb1b475da5df374fd9ad +5689811a183c61a50f98f4babebc2837878049899a52a57be670674cb23d8e90721f90a4d2fa3802cb35762680fd800ecd7551dc18eb899138e3c943d7e503b6 +b01d583deee5f99824e290b4ba3f364eac4a430883b3c092d4eca8f946c916422ecab927f52ea42b89a1cd59c254f919b0e85e6535d135a8de20f20b8c12c3b0 +0c895fcf6720192de6bf3b9e89ecdbd6596cbcdd8eb28e7c365ecc4ec1ff1460f53fe813d3cc7f5b7f020000ffff0300504b030414000600080000002100a5d6 +a7e7c0000000360100000b0000005f72656c732f2e72656c73848fcf6ac3300c87ef85bd83d17d51d2c31825762fa590432fa37d00e1287f68221bdb1bebdb4f +c7060abb0884a4eff7a93dfeae8bf9e194e720169aaa06c3e2433fcb68e1763dbf7f82c985a4a725085b787086a37bdbb55fbc50d1a33ccd311ba548b6309512 +0f88d94fbc52ae4264d1c910d24a45db3462247fa791715fd71f989e19e0364cd3f51652d73760ae8fa8c9ffb3c330cc9e4fc17faf2ce545046e37944c69e462 +a1a82fe353bd90a865aad41ed0b5b8f9d6fd010000ffff0300504b0304140006000800000021006b799616830000008a0000001c0000007468656d652f746865 +6d652f7468656d654d616e616765722e786d6c0ccc4d0ac3201040e17da17790d93763bb284562b2cbaebbf600439c1a41c7a0d29fdbd7e5e38337cedf14d59b +4b0d592c9c070d8a65cd2e88b7f07c2ca71ba8da481cc52c6ce1c715e6e97818c9b48d13df49c873517d23d59085adb5dd20d6b52bd521ef2cdd5eb9246a3d8b +4757e8d3f729e245eb2b260a0238fd010000ffff0300504b030414000600080000002100b6f4679893070000c9200000160000007468656d652f7468656d652f +7468656d65312e786d6cec59cd8b1bc915bf07f23f347d97f5d5ad8fc1f2a24fcfda33b6b164873dd648a5eef2547789aad28cc56208de532e81c026e49085bd +ed21842cecc22eb9e48f31d8249b3f22afaa5bdd5552c99e191c3061463074977eefd5afde7bf5de53d5ddcf5e26d4bbc05c1096f6fcfa9d9aefe174ce16248d +7afeb3d9a4d2f13d2151ba4094a5b8e76fb0f03fbbf7eb5fdd454732c609f6403e1547a8e7c752ae8eaa5531876124eeb0154ee1bb25e30992f0caa3ea82a34b +d09bd06aa3566b55134452df4b51026a1f2f97648ebd9952e9dfdb2a1f53784da5500373caa74a35b6243476715e5708b11143cabd0b447b3eccb3609733fc52 +fa1e4542c2173dbfa6fffceabdbb5574940b517940d6909be8bf5c2e17589c37f49c3c3a2b260d823068f50bfd1a40e53e6edc1eb7c6ad429f06a0f91c569a71 +b175b61bc320c71aa0ecd1a17bd41e35eb16ded0dfdce3dc0fd5c7c26b50a63fd8c34f2643b0a285d7a00c1feee1c3417730b2f56b50866fede1dbb5fe28685b +fa3528a6243ddf43d7c25673b85d6d0159327aec8477c360d26ee4ca4b144443115d6a8a254be5a1584bd00bc6270050408a24493db959e1259a43140f112567 +9c7827248a21f056286502866b8ddaa4d684ffea13e827ed5174849121ad780113b137a4f87862cec94af6fc07a0d537206f7ffef9cdeb1fdfbcfee9cd575fbd +79fdf77c6eadca923b466964cafdf2dd1ffef3cd6fbd7ffff0ed2f5fff319b7a172f4cfcbbbffdeedd3ffef93ef5b0e2d2146ffff4fdbb1fbf7ffbe7dfffebaf +5f3bb4f7393a33e1339260e13dc297de5396c0021dfcf119bf9ec42c46c494e8a791402952b338f48f656ca11f6d10450edc00db767cce21d5b880f7d72f2cc2 +d398af2571687c182716f094313a60dc6985876a2ec3ccb3751ab927e76b13f714a10bd7dc43945a5e1eaf579063894be530c616cd2714a5124538c5d253dfb1 +738c1dabfb8210cbaea764ce99604be97d41bc01224e93ccc899154da5d03149c02f1b1741f0b7659bd3e7de8051d7aa47f8c246c2de40d4417e86a965c6fb68 +2d51e252394309350d7e8264ec2239ddf0b9891b0b099e8e3065de78818570c93ce6b05ec3e90f21cdb8dd7e4a37898de4929cbb749e20c64ce4889d0f6394ac +5cd829496313fbb938871045de13265df05366ef10f50e7e40e941773f27d872f787b3c133c8b026a53240d4376beef0e57dccacf89d6ee8126157aae9f3c44a +b17d4e9cd131584756689f604cd1255a60ec3dfbdcc160c05696cd4bd20f62c82ac7d815580f901dabea3dc5027a25d5dcece7c91322ac909de2881de073bad9 +493c1b9426881fd2fc08bc6eda7c0ca52e7105c0633a3f37818f08f480102f4ea33c16a0c308ee835a9fc4c82a60ea5db8e375c32dff5d658fc1be7c61d1b8c2 +be04197c6d1948eca6cc7b6d3343d49aa00c9819822ec3956e41c4727f29a28aab165b3be596f6a62ddd00dd91d5f42424fd6007b4d3fb84ffbbde073a8cb77f +f9c6b10f3e4ebfe3566c25ab6b763a8792c9f14e7f7308b7dbd50c195f904fbfa919a175fa04431dd9cf58b73dcd6d4fe3ffdff73487f6f36d2773a8dfb8ed64 +7ce8306e3b99fc70e5e3743265f3027d8d3af0c80e7af4b14f72f0d46749289dca0dc527421ffc08f83db398c0a092d3279eb838055cc5f0a8ca1c4c60e1228e +b48cc799fc0d91f134462b381daafb4a492472d591f0564cc0a1911e76ea5678ba4e4ed9223becacd7d5c16656590592e5782d2cc6e1a04a66e856bb3cc02bd4 +6bb6913e68dd1250b2d721614c6693683a48b4b783ca48fa58178ce620a157f65158741d2c3a4afdd6557b2c805ae115f8c1edc1cff49e1f06200242701e07cd +f942f92973f5d6bbda991fd3d3878c69450034d8db08283ddd555c0f2e4fad2e0bb52b78da2261849b4d425b46377822869fc17974aad1abd0b8aeafbba54b2d +7aca147a3e08ad9246bbf33e1637f535c8ede6069a9a9982a6de65cf6f35430899395af5fc251c1ac363b282d811ea3717a211dcbccc25cf36fc4d32cb8a0b39 +4222ce0cae934e960d122231f728497abe5a7ee1069aea1ca2b9d51b90103e59725d482b9f1a3970baed64bc5ce2b934dd6e8c284b67af90e1b35ce1fc568bdf +1cac24d91adc3d8d1797de195df3a708422c6cd795011744c0dd413db3e682c0655891c8caf8db294c79da356fa3740c65e388ae62945714339967709dca0b3a +faadb081f196af190c6a98242f8467912ab0a651ad6a5a548d8cc3c1aafb6121653923699635d3ca2aaa6abab39835c3b60cecd8f26645de60b53531e434b3c2 +67a97b37e576b7b96ea74f28aa0418bcb09fa3ea5ea12018d4cac92c6a8af17e1a56393b1fb56bc776811fa07695226164fdd656ed8edd8a1ae19c0e066f54f9 +416e376a6168b9ed2bb5a5f5adb979b1cdce5e40f2184197bba6526857c2c92e47d0104d754f92a50dd8222f65be35e0c95b73d2f3bfac85fd60d80887955a27 +1c57826650ab74c27eb3d20fc3667d1cd66ba341e31514161927f530bbb19fc00506dde4f7f67a7cefee3ed9ded1dc99b3a4caf4dd7c5513d777f7f5c6e1bb7b +8f40d2f9b2d598749bdd41abd26df627956034e854bac3d6a0326a0ddba3c9681876ba9357be77a1c141bf390c5ae34ea5551f0e2b41aba6e877ba9576d068f4 +8376bf330efaaff23606569ea58fdc16605ecdebde7f010000ffff0300504b0304140006000800000021000dd1909fb60000001b010000270000007468656d65 +2f7468656d652f5f72656c732f7468656d654d616e616765722e786d6c2e72656c73848f4d0ac2301484f78277086f6fd3ba109126dd88d0add40384e4350d36 +3f2451eced0dae2c082e8761be9969bb979dc9136332de3168aa1a083ae995719ac16db8ec8e4052164e89d93b64b060828e6f37ed1567914b284d262452282e +3198720e274a939cd08a54f980ae38a38f56e422a3a641c8bbd048f7757da0f19b017cc524bd62107bd5001996509affb3fd381a89672f1f165dfe514173d985 +0528a2c6cce0239baa4c04ca5bbabac4df000000ffff0300504b01022d0014000600080000002100e9de0fbfff0000001c020000130000000000000000000000 +0000000000005b436f6e74656e745f54797065735d2e786d6c504b01022d0014000600080000002100a5d6a7e7c0000000360100000b00000000000000000000 +000000300100005f72656c732f2e72656c73504b01022d00140006000800000021006b799616830000008a0000001c0000000000000000000000000019020000 +7468656d652f7468656d652f7468656d654d616e616765722e786d6c504b01022d0014000600080000002100b6f4679893070000c92000001600000000000000 +000000000000d60200007468656d652f7468656d652f7468656d65312e786d6c504b01022d00140006000800000021000dd1909fb60000001b01000027000000 +000000000000000000009d0a00007468656d652f7468656d652f5f72656c732f7468656d654d616e616765722e786d6c2e72656c73504b050600000000050005005d010000980b00000000} +{\*\colorschememapping 3c3f786d6c2076657273696f6e3d22312e302220656e636f64696e673d225554462d3822207374616e64616c6f6e653d22796573223f3e0d0a3c613a636c724d +617020786d6c6e733a613d22687474703a2f2f736368656d61732e6f70656e786d6c666f726d6174732e6f72672f64726177696e676d6c2f323030362f6d6169 +6e22206267313d226c743122207478313d22646b3122206267323d226c743222207478323d22646b322220616363656e74313d22616363656e74312220616363 +656e74323d22616363656e74322220616363656e74333d22616363656e74332220616363656e74343d22616363656e74342220616363656e74353d22616363656e74352220616363656e74363d22616363656e74362220686c696e6b3d22686c696e6b2220666f6c486c696e6b3d22666f6c486c696e6b222f3e} +{\*\latentstyles\lsdstimax376\lsdlockeddef0\lsdsemihiddendef0\lsdunhideuseddef0\lsdqformatdef0\lsdprioritydef99{\lsdlockedexcept \lsdqformat1 \lsdpriority0 \lsdlocked0 Normal;\lsdqformat1 \lsdpriority9 \lsdlocked0 heading 1; +\lsdsemihidden1 \lsdunhideused1 \lsdqformat1 \lsdpriority9 \lsdlocked0 heading 2;\lsdsemihidden1 \lsdunhideused1 \lsdqformat1 \lsdpriority9 \lsdlocked0 heading 3;\lsdsemihidden1 \lsdunhideused1 \lsdqformat1 \lsdpriority9 \lsdlocked0 heading 4; +\lsdsemihidden1 \lsdunhideused1 \lsdqformat1 \lsdpriority9 \lsdlocked0 heading 5;\lsdsemihidden1 \lsdunhideused1 \lsdqformat1 \lsdpriority9 \lsdlocked0 heading 6;\lsdsemihidden1 \lsdunhideused1 \lsdqformat1 \lsdpriority9 \lsdlocked0 heading 7; +\lsdsemihidden1 \lsdunhideused1 \lsdqformat1 \lsdpriority9 \lsdlocked0 heading 8;\lsdsemihidden1 \lsdunhideused1 \lsdqformat1 \lsdpriority9 \lsdlocked0 heading 9;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 index 1; +\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 index 2;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 index 3;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 index 4;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 index 5; +\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 index 6;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 index 7;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 index 8;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 index 9; +\lsdsemihidden1 \lsdunhideused1 \lsdpriority39 \lsdlocked0 toc 1;\lsdsemihidden1 \lsdunhideused1 \lsdpriority39 \lsdlocked0 toc 2;\lsdsemihidden1 \lsdunhideused1 \lsdpriority39 \lsdlocked0 toc 3; +\lsdsemihidden1 \lsdunhideused1 \lsdpriority39 \lsdlocked0 toc 4;\lsdsemihidden1 \lsdunhideused1 \lsdpriority39 \lsdlocked0 toc 5;\lsdsemihidden1 \lsdunhideused1 \lsdpriority39 \lsdlocked0 toc 6; +\lsdsemihidden1 \lsdunhideused1 \lsdpriority39 \lsdlocked0 toc 7;\lsdsemihidden1 \lsdunhideused1 \lsdpriority39 \lsdlocked0 toc 8;\lsdsemihidden1 \lsdunhideused1 \lsdpriority39 \lsdlocked0 toc 9;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Normal Indent; +\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 footnote text;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 annotation text;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 header;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 footer; +\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 index heading;\lsdsemihidden1 \lsdunhideused1 \lsdqformat1 \lsdpriority35 \lsdlocked0 caption;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 table of figures; +\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 envelope address;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 envelope return;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 footnote reference;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 annotation reference; +\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 line number;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 page number;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 endnote reference;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 endnote text; +\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 table of authorities;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 macro;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 toa heading;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 List; +\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 List Bullet;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 List Number;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 List 2;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 List 3; +\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 List 4;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 List 5;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 List Bullet 2;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 List Bullet 3; +\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 List Bullet 4;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 List Bullet 5;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 List Number 2;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 List Number 3; +\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 List Number 4;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 List Number 5;\lsdqformat1 \lsdpriority10 \lsdlocked0 Title;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Closing; +\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Signature;\lsdsemihidden1 \lsdunhideused1 \lsdpriority1 \lsdlocked0 Default Paragraph Font;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Body Text;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Body Text Indent; +\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 List Continue;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 List Continue 2;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 List Continue 3;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 List Continue 4; +\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 List Continue 5;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Message Header;\lsdqformat1 \lsdpriority11 \lsdlocked0 Subtitle;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Salutation; +\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Date;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Body Text First Indent;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Body Text First Indent 2;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Note Heading; +\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Body Text 2;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Body Text 3;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Body Text Indent 2;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Body Text Indent 3; +\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Block Text;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Hyperlink;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 FollowedHyperlink;\lsdqformat1 \lsdpriority22 \lsdlocked0 Strong; +\lsdqformat1 \lsdpriority20 \lsdlocked0 Emphasis;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Document Map;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Plain Text;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 E-mail Signature; +\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 HTML Top of Form;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 HTML Bottom of Form;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Normal (Web);\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 HTML Acronym; +\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 HTML Address;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 HTML Cite;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 HTML Code;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 HTML Definition; +\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 HTML Keyboard;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 HTML Preformatted;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 HTML Sample;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 HTML Typewriter; +\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 HTML Variable;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 annotation subject;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 No List;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Outline List 1; +\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Outline List 2;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Outline List 3;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Balloon Text;\lsdpriority39 \lsdlocked0 Table Grid; +\lsdsemihidden1 \lsdlocked0 Placeholder Text;\lsdqformat1 \lsdpriority1 \lsdlocked0 No Spacing;\lsdpriority60 \lsdlocked0 Light Shading;\lsdpriority61 \lsdlocked0 Light List;\lsdpriority62 \lsdlocked0 Light Grid; +\lsdpriority63 \lsdlocked0 Medium Shading 1;\lsdpriority64 \lsdlocked0 Medium Shading 2;\lsdpriority65 \lsdlocked0 Medium List 1;\lsdpriority66 \lsdlocked0 Medium List 2;\lsdpriority67 \lsdlocked0 Medium Grid 1;\lsdpriority68 \lsdlocked0 Medium Grid 2; +\lsdpriority69 \lsdlocked0 Medium Grid 3;\lsdpriority70 \lsdlocked0 Dark List;\lsdpriority71 \lsdlocked0 Colorful Shading;\lsdpriority72 \lsdlocked0 Colorful List;\lsdpriority73 \lsdlocked0 Colorful Grid;\lsdpriority60 \lsdlocked0 Light Shading Accent 1; +\lsdpriority61 \lsdlocked0 Light List Accent 1;\lsdpriority62 \lsdlocked0 Light Grid Accent 1;\lsdpriority63 \lsdlocked0 Medium Shading 1 Accent 1;\lsdpriority64 \lsdlocked0 Medium Shading 2 Accent 1;\lsdpriority65 \lsdlocked0 Medium List 1 Accent 1; +\lsdsemihidden1 \lsdlocked0 Revision;\lsdqformat1 \lsdpriority34 \lsdlocked0 List Paragraph;\lsdqformat1 \lsdpriority29 \lsdlocked0 Quote;\lsdqformat1 \lsdpriority30 \lsdlocked0 Intense Quote;\lsdpriority66 \lsdlocked0 Medium List 2 Accent 1; +\lsdpriority67 \lsdlocked0 Medium Grid 1 Accent 1;\lsdpriority68 \lsdlocked0 Medium Grid 2 Accent 1;\lsdpriority69 \lsdlocked0 Medium Grid 3 Accent 1;\lsdpriority70 \lsdlocked0 Dark List Accent 1;\lsdpriority71 \lsdlocked0 Colorful Shading Accent 1; +\lsdpriority72 \lsdlocked0 Colorful List Accent 1;\lsdpriority73 \lsdlocked0 Colorful Grid Accent 1;\lsdpriority60 \lsdlocked0 Light Shading Accent 2;\lsdpriority61 \lsdlocked0 Light List Accent 2;\lsdpriority62 \lsdlocked0 Light Grid Accent 2; +\lsdpriority63 \lsdlocked0 Medium Shading 1 Accent 2;\lsdpriority64 \lsdlocked0 Medium Shading 2 Accent 2;\lsdpriority65 \lsdlocked0 Medium List 1 Accent 2;\lsdpriority66 \lsdlocked0 Medium List 2 Accent 2; +\lsdpriority67 \lsdlocked0 Medium Grid 1 Accent 2;\lsdpriority68 \lsdlocked0 Medium Grid 2 Accent 2;\lsdpriority69 \lsdlocked0 Medium Grid 3 Accent 2;\lsdpriority70 \lsdlocked0 Dark List Accent 2;\lsdpriority71 \lsdlocked0 Colorful Shading Accent 2; +\lsdpriority72 \lsdlocked0 Colorful List Accent 2;\lsdpriority73 \lsdlocked0 Colorful Grid Accent 2;\lsdpriority60 \lsdlocked0 Light Shading Accent 3;\lsdpriority61 \lsdlocked0 Light List Accent 3;\lsdpriority62 \lsdlocked0 Light Grid Accent 3; +\lsdpriority63 \lsdlocked0 Medium Shading 1 Accent 3;\lsdpriority64 \lsdlocked0 Medium Shading 2 Accent 3;\lsdpriority65 \lsdlocked0 Medium List 1 Accent 3;\lsdpriority66 \lsdlocked0 Medium List 2 Accent 3; +\lsdpriority67 \lsdlocked0 Medium Grid 1 Accent 3;\lsdpriority68 \lsdlocked0 Medium Grid 2 Accent 3;\lsdpriority69 \lsdlocked0 Medium Grid 3 Accent 3;\lsdpriority70 \lsdlocked0 Dark List Accent 3;\lsdpriority71 \lsdlocked0 Colorful Shading Accent 3; +\lsdpriority72 \lsdlocked0 Colorful List Accent 3;\lsdpriority73 \lsdlocked0 Colorful Grid Accent 3;\lsdpriority60 \lsdlocked0 Light Shading Accent 4;\lsdpriority61 \lsdlocked0 Light List Accent 4;\lsdpriority62 \lsdlocked0 Light Grid Accent 4; +\lsdpriority63 \lsdlocked0 Medium Shading 1 Accent 4;\lsdpriority64 \lsdlocked0 Medium Shading 2 Accent 4;\lsdpriority65 \lsdlocked0 Medium List 1 Accent 4;\lsdpriority66 \lsdlocked0 Medium List 2 Accent 4; +\lsdpriority67 \lsdlocked0 Medium Grid 1 Accent 4;\lsdpriority68 \lsdlocked0 Medium Grid 2 Accent 4;\lsdpriority69 \lsdlocked0 Medium Grid 3 Accent 4;\lsdpriority70 \lsdlocked0 Dark List Accent 4;\lsdpriority71 \lsdlocked0 Colorful Shading Accent 4; +\lsdpriority72 \lsdlocked0 Colorful List Accent 4;\lsdpriority73 \lsdlocked0 Colorful Grid Accent 4;\lsdpriority60 \lsdlocked0 Light Shading Accent 5;\lsdpriority61 \lsdlocked0 Light List Accent 5;\lsdpriority62 \lsdlocked0 Light Grid Accent 5; +\lsdpriority63 \lsdlocked0 Medium Shading 1 Accent 5;\lsdpriority64 \lsdlocked0 Medium Shading 2 Accent 5;\lsdpriority65 \lsdlocked0 Medium List 1 Accent 5;\lsdpriority66 \lsdlocked0 Medium List 2 Accent 5; +\lsdpriority67 \lsdlocked0 Medium Grid 1 Accent 5;\lsdpriority68 \lsdlocked0 Medium Grid 2 Accent 5;\lsdpriority69 \lsdlocked0 Medium Grid 3 Accent 5;\lsdpriority70 \lsdlocked0 Dark List Accent 5;\lsdpriority71 \lsdlocked0 Colorful Shading Accent 5; +\lsdpriority72 \lsdlocked0 Colorful List Accent 5;\lsdpriority73 \lsdlocked0 Colorful Grid Accent 5;\lsdpriority60 \lsdlocked0 Light Shading Accent 6;\lsdpriority61 \lsdlocked0 Light List Accent 6;\lsdpriority62 \lsdlocked0 Light Grid Accent 6; +\lsdpriority63 \lsdlocked0 Medium Shading 1 Accent 6;\lsdpriority64 \lsdlocked0 Medium Shading 2 Accent 6;\lsdpriority65 \lsdlocked0 Medium List 1 Accent 6;\lsdpriority66 \lsdlocked0 Medium List 2 Accent 6; +\lsdpriority67 \lsdlocked0 Medium Grid 1 Accent 6;\lsdpriority68 \lsdlocked0 Medium Grid 2 Accent 6;\lsdpriority69 \lsdlocked0 Medium Grid 3 Accent 6;\lsdpriority70 \lsdlocked0 Dark List Accent 6;\lsdpriority71 \lsdlocked0 Colorful Shading Accent 6; +\lsdpriority72 \lsdlocked0 Colorful List Accent 6;\lsdpriority73 \lsdlocked0 Colorful Grid Accent 6;\lsdqformat1 \lsdpriority19 \lsdlocked0 Subtle Emphasis;\lsdqformat1 \lsdpriority21 \lsdlocked0 Intense Emphasis; +\lsdqformat1 \lsdpriority31 \lsdlocked0 Subtle Reference;\lsdqformat1 \lsdpriority32 \lsdlocked0 Intense Reference;\lsdqformat1 \lsdpriority33 \lsdlocked0 Book Title;\lsdsemihidden1 \lsdunhideused1 \lsdpriority37 \lsdlocked0 Bibliography; +\lsdsemihidden1 \lsdunhideused1 \lsdqformat1 \lsdpriority39 \lsdlocked0 TOC Heading;\lsdpriority41 \lsdlocked0 Plain Table 1;\lsdpriority42 \lsdlocked0 Plain Table 2;\lsdpriority43 \lsdlocked0 Plain Table 3;\lsdpriority44 \lsdlocked0 Plain Table 4; +\lsdpriority45 \lsdlocked0 Plain Table 5;\lsdpriority40 \lsdlocked0 Grid Table Light;\lsdpriority46 \lsdlocked0 Grid Table 1 Light;\lsdpriority47 \lsdlocked0 Grid Table 2;\lsdpriority48 \lsdlocked0 Grid Table 3;\lsdpriority49 \lsdlocked0 Grid Table 4; +\lsdpriority50 \lsdlocked0 Grid Table 5 Dark;\lsdpriority51 \lsdlocked0 Grid Table 6 Colorful;\lsdpriority52 \lsdlocked0 Grid Table 7 Colorful;\lsdpriority46 \lsdlocked0 Grid Table 1 Light Accent 1;\lsdpriority47 \lsdlocked0 Grid Table 2 Accent 1; +\lsdpriority48 \lsdlocked0 Grid Table 3 Accent 1;\lsdpriority49 \lsdlocked0 Grid Table 4 Accent 1;\lsdpriority50 \lsdlocked0 Grid Table 5 Dark Accent 1;\lsdpriority51 \lsdlocked0 Grid Table 6 Colorful Accent 1; +\lsdpriority52 \lsdlocked0 Grid Table 7 Colorful Accent 1;\lsdpriority46 \lsdlocked0 Grid Table 1 Light Accent 2;\lsdpriority47 \lsdlocked0 Grid Table 2 Accent 2;\lsdpriority48 \lsdlocked0 Grid Table 3 Accent 2; +\lsdpriority49 \lsdlocked0 Grid Table 4 Accent 2;\lsdpriority50 \lsdlocked0 Grid Table 5 Dark Accent 2;\lsdpriority51 \lsdlocked0 Grid Table 6 Colorful Accent 2;\lsdpriority52 \lsdlocked0 Grid Table 7 Colorful Accent 2; +\lsdpriority46 \lsdlocked0 Grid Table 1 Light Accent 3;\lsdpriority47 \lsdlocked0 Grid Table 2 Accent 3;\lsdpriority48 \lsdlocked0 Grid Table 3 Accent 3;\lsdpriority49 \lsdlocked0 Grid Table 4 Accent 3; +\lsdpriority50 \lsdlocked0 Grid Table 5 Dark Accent 3;\lsdpriority51 \lsdlocked0 Grid Table 6 Colorful Accent 3;\lsdpriority52 \lsdlocked0 Grid Table 7 Colorful Accent 3;\lsdpriority46 \lsdlocked0 Grid Table 1 Light Accent 4; +\lsdpriority47 \lsdlocked0 Grid Table 2 Accent 4;\lsdpriority48 \lsdlocked0 Grid Table 3 Accent 4;\lsdpriority49 \lsdlocked0 Grid Table 4 Accent 4;\lsdpriority50 \lsdlocked0 Grid Table 5 Dark Accent 4; +\lsdpriority51 \lsdlocked0 Grid Table 6 Colorful Accent 4;\lsdpriority52 \lsdlocked0 Grid Table 7 Colorful Accent 4;\lsdpriority46 \lsdlocked0 Grid Table 1 Light Accent 5;\lsdpriority47 \lsdlocked0 Grid Table 2 Accent 5; +\lsdpriority48 \lsdlocked0 Grid Table 3 Accent 5;\lsdpriority49 \lsdlocked0 Grid Table 4 Accent 5;\lsdpriority50 \lsdlocked0 Grid Table 5 Dark Accent 5;\lsdpriority51 \lsdlocked0 Grid Table 6 Colorful Accent 5; +\lsdpriority52 \lsdlocked0 Grid Table 7 Colorful Accent 5;\lsdpriority46 \lsdlocked0 Grid Table 1 Light Accent 6;\lsdpriority47 \lsdlocked0 Grid Table 2 Accent 6;\lsdpriority48 \lsdlocked0 Grid Table 3 Accent 6; +\lsdpriority49 \lsdlocked0 Grid Table 4 Accent 6;\lsdpriority50 \lsdlocked0 Grid Table 5 Dark Accent 6;\lsdpriority51 \lsdlocked0 Grid Table 6 Colorful Accent 6;\lsdpriority52 \lsdlocked0 Grid Table 7 Colorful Accent 6; +\lsdpriority46 \lsdlocked0 List Table 1 Light;\lsdpriority47 \lsdlocked0 List Table 2;\lsdpriority48 \lsdlocked0 List Table 3;\lsdpriority49 \lsdlocked0 List Table 4;\lsdpriority50 \lsdlocked0 List Table 5 Dark; +\lsdpriority51 \lsdlocked0 List Table 6 Colorful;\lsdpriority52 \lsdlocked0 List Table 7 Colorful;\lsdpriority46 \lsdlocked0 List Table 1 Light Accent 1;\lsdpriority47 \lsdlocked0 List Table 2 Accent 1;\lsdpriority48 \lsdlocked0 List Table 3 Accent 1; +\lsdpriority49 \lsdlocked0 List Table 4 Accent 1;\lsdpriority50 \lsdlocked0 List Table 5 Dark Accent 1;\lsdpriority51 \lsdlocked0 List Table 6 Colorful Accent 1;\lsdpriority52 \lsdlocked0 List Table 7 Colorful Accent 1; +\lsdpriority46 \lsdlocked0 List Table 1 Light Accent 2;\lsdpriority47 \lsdlocked0 List Table 2 Accent 2;\lsdpriority48 \lsdlocked0 List Table 3 Accent 2;\lsdpriority49 \lsdlocked0 List Table 4 Accent 2; +\lsdpriority50 \lsdlocked0 List Table 5 Dark Accent 2;\lsdpriority51 \lsdlocked0 List Table 6 Colorful Accent 2;\lsdpriority52 \lsdlocked0 List Table 7 Colorful Accent 2;\lsdpriority46 \lsdlocked0 List Table 1 Light Accent 3; +\lsdpriority47 \lsdlocked0 List Table 2 Accent 3;\lsdpriority48 \lsdlocked0 List Table 3 Accent 3;\lsdpriority49 \lsdlocked0 List Table 4 Accent 3;\lsdpriority50 \lsdlocked0 List Table 5 Dark Accent 3; +\lsdpriority51 \lsdlocked0 List Table 6 Colorful Accent 3;\lsdpriority52 \lsdlocked0 List Table 7 Colorful Accent 3;\lsdpriority46 \lsdlocked0 List Table 1 Light Accent 4;\lsdpriority47 \lsdlocked0 List Table 2 Accent 4; +\lsdpriority48 \lsdlocked0 List Table 3 Accent 4;\lsdpriority49 \lsdlocked0 List Table 4 Accent 4;\lsdpriority50 \lsdlocked0 List Table 5 Dark Accent 4;\lsdpriority51 \lsdlocked0 List Table 6 Colorful Accent 4; +\lsdpriority52 \lsdlocked0 List Table 7 Colorful Accent 4;\lsdpriority46 \lsdlocked0 List Table 1 Light Accent 5;\lsdpriority47 \lsdlocked0 List Table 2 Accent 5;\lsdpriority48 \lsdlocked0 List Table 3 Accent 5; +\lsdpriority49 \lsdlocked0 List Table 4 Accent 5;\lsdpriority50 \lsdlocked0 List Table 5 Dark Accent 5;\lsdpriority51 \lsdlocked0 List Table 6 Colorful Accent 5;\lsdpriority52 \lsdlocked0 List Table 7 Colorful Accent 5; +\lsdpriority46 \lsdlocked0 List Table 1 Light Accent 6;\lsdpriority47 \lsdlocked0 List Table 2 Accent 6;\lsdpriority48 \lsdlocked0 List Table 3 Accent 6;\lsdpriority49 \lsdlocked0 List Table 4 Accent 6; +\lsdpriority50 \lsdlocked0 List Table 5 Dark Accent 6;\lsdpriority51 \lsdlocked0 List Table 6 Colorful Accent 6;\lsdpriority52 \lsdlocked0 List Table 7 Colorful Accent 6;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Mention; +\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Smart Hyperlink;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Hashtag;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Unresolved Mention;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Smart Link;}}{\*\datastore 01050000 +02000000180000004d73786d6c322e534158584d4c5265616465722e362e3000000000000000000000060000 +d0cf11e0a1b11ae1000000000000000000000000000000003e000300feff090006000000000000000000000001000000010000000000000000100000feffffff00000000feffffff0000000000000000ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff +ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff +ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff +ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff +fffffffffffffffffdfffffffeffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff +ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff +ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff +ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff +ffffffffffffffffffffffffffffffff52006f006f007400200045006e00740072007900000000000000000000000000000000000000000000000000000000000000000000000000000000000000000016000500ffffffffffffffffffffffff0c6ad98892f1d411a65f0040963251e500000000000000000000000000bf +4070e7f9d401feffffff00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000ffffffffffffffffffffffff00000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000ffffffffffffffffffffffff0000000000000000000000000000000000000000000000000000 +000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000ffffffffffffffffffffffff000000000000000000000000000000000000000000000000 +0000000000000000000000000000000000000000000000000105000000000000}} \ No newline at end of file diff --git a/README.md b/README.md new file mode 100644 index 00000000..ef735235 --- /dev/null +++ b/README.md @@ -0,0 +1,194 @@ +# Jami-qt + +`jami-qt` is the cross platform client for Jami. For now, it's mainly used for the Windows platform and is not tested on other platforms. + +![jami-logo](images/logo-jami-standard-coul.png) + + +For more information about the jami project, see the following: + +- Main website: https://jami.net/ +- Bug tracker: https://git.jami.net/ +- Repositories: https://gerrit-ring.savoirfairelinux.com + +## Building On Native Windows +--- + +Only 64-bit MSVC build can be compiled. + +> Note: command ```./make-ring.py --init``` is not required on the Windows build
+ +**Setup Before Building:** +- Download [Qt (Open Source)](https://www.qt.io/download-open-source?hsCtaTracking=9f6a2170-a938-42df-a8e2-a9f0b1d6cdce%7C6cb0de4f-9bb5-4778-ab02-bfb62735f3e5)
+ + | | Prebuild | Module | + |---|---|---| + | Components: | msvc2017_64 | Qt WebEngine | + +- Download [Visual Studio](https://visualstudio.microsoft.com/) (version >= 2015)
+- Install Qt Vs Tools under extensions, and configure msvc2017_64 path under Qt Options
+ + | | Qt Version | SDK | Toolset | + |---|---|---|---| + | Minimum requirement: | 5.9.4 | 10.0.16299.0 | V141 | + +- Install [Python3](https://www.python.org/downloads/) for Windows + +**Start Building** +- Using Command Prompt +```sh + git clone https://review.jami.net/ring-project + cd ring-project/ + git submodule update --init daemon lrc client-windows + git submodule update --recursive --remote daemon lrc client-windows +``` +- Using **Elevated Command Prompt** +```sh + python make-ring.py --dependencies +``` + +> Note: +> 1. This command will install **chocolatey** which may require you to restart the Command Prompt to be able to use it. +> 2. This command will install **msys2 (64 bit)** by using chocolatey command which may cause issues below:
+> a. Choco may require you to restart the Command Prompt after finishing installing msys2.
+> b. Only if you have already installed msys2 (64 bit) under the default installation folder, we will use the existing one. +> 3. This command will install **strawberry perl** by using chocolatey command which may fail if you have already installed it. +> 4. This command will install **cmake** by using chocolatey command which will not add cmake into PATH (environment variable).
+> +> The issue 1, 2(a), 3 can be solved by restarting the Command Prompt under Administrator right and re-run the command.
+> The issue 3 can be solved by uninstalling your current strawberry perl and re-run the command.
+> The issue 4 can be solved by adding the location of the cmake.exe into PATH.
+ +- Using a new **Non-Elevated Command Prompt** +```sh + python make-ring.py --install +``` +- Then you should be able to use the Visual Studio Solution file in client-windows folder **(Configuration = Release, Platform = x64)** + +> Note:
+> To control the toolset and the sdk version that are used by msbuild, you can use ```--toolset``` and ```--sdk``` options
+> To control which Qt version should be used (qmake, windeployqt), uou can use ```--qtver``` option
+> By default: ```toolset=v141```, ```sdk=10.0.16299.0```, ```qtver=5.9.4```
+> For example: +```sh + python make-ring.py --install --toolset v142 --sdk 10.0.18362.0 --qtver 5.12.0 +``` + +### Build Module individually +--- + +- Jami-qt also support building each module (daemon, lrc, jami-qt) seperately + +**Daemon** + +- Make sure that dependencies is built by make-ring.py +- On MSVC folder (ring-project\daemon\MSVC): +```sh + cmake -DCMAKE_CONFIGURATION_TYPES="ReleaseLib_win32" -DCMAKE_VS_PLATFORM_NAME="x64" -G "Visual Studio 16 2019" -A x64 -T '$(DefaultPlatformToolset)' .. + python winmake.py -b daemon +``` +- This will generate a ```.lib``` file in the path of ring-project\daemon\MSVC\x64\ReleaseLib_win32\bin + +> Note: each dependencies contrib for daemon can also be updated individually
+> For example: +```bash + python winmake.py -b opendht +``` + +**Lrc** + +- Make sure that daemon is built first + +```bash + cd lrc + python make-lrc.py -gb +``` + +**Jami-qt** + +- Make sure that daemon, lrc are built first + +```bash + cd client-windows + pandoc -f markdown -t html5 -o changelog.html changelog.md + python make-client.py -d + python make-client.py -b + powershell -ExecutionPolicy Unrestricted -File copy-runtime-files.ps1 +``` + +**Note** +- For all python scripts, both ```--toolset``` and ```--sdk``` options are available. +- For more available options, run scripts with ```-h``` option. +- ```--qtver``` option is available on ```make-lrc.py``` and ```make-client.py```. + +## Packaging On Native Windows +--- + +- To be able to generate a msi package, first download and install [Wixtoolset](https://wixtoolset.org/releases/). +- In Visual Studio, download WiX Toolset Visual Studio Extension. +- Build client-windows project first, then the JamiInstaller project, msi package should be stored in ring-project\client-windows\JamiInstaller\bin\Release + +## Linux +--- + +> For now, this process is experimental. + +- LibRing and LibRingClient +must be installed first. If you have not already done so, go to the +[\#How to Build LibRing (or +Daemon)](#How_to_Build_LibRing_(or_Daemon) "wikilink") and [\#How to +Build LibRingClient (or +LRC)](#How_to_Build_LibRingClient_(or_LRC) "wikilink") sections. +- Building the whole ring-project is recommended, however, lrc might need to be rebuilt with cmake option ```-DCMAKE_INSTALL_PREFIX=/usr``` + +#### Other Requirements + +- Qt 5.9.4 (qt open source) +- libqt5svg*, qtwebengine5-dev, qtmultimedia5-dev, qtdeclarative5-dev, pandoc + +#### Getting the Source Code + +```bash + git clone https://review.jami.net/ring-client-windows +``` + +#### Build Instructions + +**Windows Client dependencies** + +- For Debian based: +```bash + sudo apt install qtmultimedia5-dev libqt5svg5* qtwebengine5-dev qtdeclarative5-dev qtquickcontrols2-5-dev qml-module-qtquick* pandoc +``` +- For Fedora: +```bash + sudo dnf install qt5-qtsvg-devel qt5-qtwebengine-devel qt5-qtmultimedia-devel qt5-qtdeclarative-devel qt5-qtquickcontrols2-devel pandoc +``` + +**Build Windows Client** + +```bash + cd ring-client-windows + pandoc -f markdown -t html5 -o changelog.html changelog.md + mkdir build + cd build + qmake -qt=qt5 ../jami-qt.pro + make -j9 +``` +- Then, you are finally ready to launch jami-qt in your build directory. + +#### Debugging + +Compile the client with `BUILD=Debug` and compile LibRingClient with +`-DCMAKE_BUILD_TYPE=Debug` + +#### Known issues + +1. The build system is not straight forward +2. Video doesn't work +3. Can't maximize/minimize window +4. Crash if the daemon is not started and installed. + +## Mac OS +--- +TBD diff --git a/changelog.md b/changelog.md new file mode 100644 index 00000000..63ae7d9b --- /dev/null +++ b/changelog.md @@ -0,0 +1,203 @@ +# 2020-03-16 + +## Bug Fixes + ++ Fixed the bug that the system notification cannot be disabled ++ Fixed video device enumeration for higher framerates ++ More reliable high dpi adaption ++ Prevent crash when video device events happen with no account + +## New Features + ++ Add type indicator ++ Movable splitter in main view ++ Connectivity improvement for calls and messages + +# 2019-12-13 + +## Bug Fixes + ++ Fixed the bug that caused lag on call overlay ++ Fixed a typo on about dialog + +## New Features + ++ Add various useful shortcuts + +# 2019-11-20 + +## Bug Fixes + ++ Fixed bug that prevented pasting multiline text into chat + +## New Features + ++ Calls now automatically un-hold when the conversation is selected ++ SIP dialpad now has A,B,C,D dtmf options + +# 2019-11-19 + +## Bug Fixes + ++ Fixed notifications popping up for outgoing calls ++ Removing conference participant selects a remaining participant conversation + +# 2019-11-15 + +## Notes + +Change version name to 'Free as in Freedom' +Linux: ffmpeg now embedded in official package for auto bitrate + hardware acceleration + +## Features + ++ callview: rework conference ui ([#1052](https://git.jami.net/savoirfairelinux/ring-client-gnome/issues/1052)) ++ JAMS: support login to an account manager ++ wizard: re-work account creation ++ chatview: add video recorder ++ chatview: add audio recorder ++ conversation: automatically accepts < 20Mb files ++ video: auto adapt bitrate ++ Beta version ++ Change logs ++ Save draft text messages + +## Bugfixes + ++ Fix multiple crash with SIP accounts ++ Fix DTMF for SIP ++ chatview: show generated avatar into the chatview ([#947](https://git.jami.net/savoirfairelinux/ring-client-gnome/issues/947)) ++ Fix account migration ++ Fix alignment in settings view ++ call: handle PEER_BUSY state ++ lrc: fix clearAllHistory ++ avmodel: sort framerates ++ sip: fix temporary item removal ++ avmodel: getCurrentRenderedDevice support conferences ++ upnp: now async ++ some deadlocks are fixed ++ some segfault are fixed ++ sip_transport: avoid PJ_ENOTSUITABLE when ipv4<->ipv6 ++ sipcall: fix rotation ++ ffmpeg: handle ebusy when opening devices ++ file transfer: fix cancel ++ conference: fix color inversion during conferences ++ lan: improve pjsip behavior in a LAN ++ [trustrequests: handle removed contacts](https://git.jami.net/savoirfairelinux/ring-daemon/issues/129) ++ dbus: only authorize one daemon per DBUS_SESSION_BUS_ADDRESS ++ Fixed crash when user has no account ++ Fixed display name changes not saving ++ Fixed not being able to change back to camera from screen share ++ Fixed utf-8 handling on display names + +## Internal changes + ++ chatview code is now in LRC and shared with the desktop clients ++ database: migrate to per account database ++ avmodel: optionally switchInput using a callId ++ video sender: send only 1 keyframe at start ++ contrib: various bump (opendht, upnp, ffmpeg, etc) ++ p2p: use one IceTransport by sub transfer ++ decoder: set fpsprobesize, use default probesize ++ ice: enable aggressive nomination to avoid latencies ++ accel: remove libdrm code ++ sipvoiplink: remove wait for completed transactions in dtor ++ Remove some thread creations ++ replace restbed by restinio ++ namedirectory: don't create temporary items during lookup ++ file transfer: use different ice for each transfer ++ manager: allow switchInput on conference + + +# 2019-08-24 + +## Features + ++ [Erase data securely before removing account](https://git.jami.net/savoirfairelinux/ring-daemon/issues/60) ++ [Negotiate calls in TCP and UDP and prefer TCP if necessary](https://git.jami.net/savoirfairelinux/ring-daemon/issues/103) ++ Improve negotiation for p2p file transfer ++ Auto change the video quality ++ Add hardware acceleration support for NVidia ++ SIP fix SMS issues + +## Bugfixes + ++ Improve connectivityChange detection and account switching. ++ Translate strings from daemon. ++ Sort resolutions by width ++ [Sort conversations when clearing history](https://git.jami.net/savoirfairelinux/ring-lrc/issues/411) ++ Fix subscriptions for new contacts ++ Hangup if contact is deleted ++ [Various deadlocks](https://git.jami.net/savoirfairelinux/ring-daemon/issues/120) + +## Internal changes + ++ LRC remove unused code ++ Change from enableAccount() to setAccountEnabled() ++ Update msgpack, gnutls, opendht ++ Rewrite code for UPnP support + +# 2019-06-20 + +## Bugfixes + ++ Improve name registration errors detection ++ Improve SIP text/plain detection ++ Fix temporary item when copy/paste a full ring id ++ SIP: Fix online status ++ [Fix audio recorder](https://git.jami.net/savoirfairelinux/ring-daemon/issues/95) ++ Fix some deadlocks ++ [Fix calls via TURN](https://git.jami.net/savoirfairelinux/ring-daemon/issues/105) ++ [Fix multi devices support for calls](https://git.jami.net/savoirfairelinux/ring-daemon/issues/120) + + +## Internal changes + ++ Cleanup daemon side ++ Update restbed ++ Update opendht to 1.9.5 ++ [Improve UPnP implementation](https://git.jami.net/savoirfairelinux/ring-daemon/issues/96) ++ Increase default video bitrate + +# 2019-05-16 + +## Features + ++ [Add peer to peer file transfer support](https://git.jami.net/savoirfairelinux/ring-project/issues/486) ++ Advanced settings: add DHT peer discovery support ++ Media Settings: add hardware acceleration support ++ [UPnP add TCP mapping support](https://git.jami.net/savoirfairelinux/ring-daemon/issues/86) + +## Bugfixes + ++ Name registration: better handling for wrong archive password ++ tls_session: close transport after cleanup ++ sip: check message utf8 validity before emitting signal + +## Internal changes + ++ Bump OpenDHT to 1.9.4 ++ Bump GNUTls to 3.6.7 ++ Bump Pjsip to (6b9212dcb4b3f781c1e922ae544b063880bc46ac + patches) ++ Internal renaming from Ring to Jami ++ Use new methods from LRC ++ Fix some data races ++ dring/dbus: unregister signals on exit + +# 2019-04-12 + +## Features + ++ (Not linked to the UI for now) Hardware encoding support + +## Bugfixes + ++ Sets up video streams upon receiving the first video frame. ++ Pulseaudio: start streams when ready + +## Internal changes + ++ Continue name migration, change data locations, binary names and methods names. ++ Nettle 3.4.1 is now required ++ Support video rotation when recording ++ Some code clean \ No newline at end of file diff --git a/copy-runtime-files.ps1 b/copy-runtime-files.ps1 new file mode 100644 index 00000000..4db58531 --- /dev/null +++ b/copy-runtime-files.ps1 @@ -0,0 +1,99 @@ +[cmdletbinding()] +param ( + [string]$mode, + [string]$qtver, + [string]$daemonDir, + [string]$lrcDir +); + +write-host "Copying runtime files..." -ForegroundColor Green + +# default values +$qtver = If ($qtver) {$qtver} Else {"5.9.4"} +$mode = If ($mode) {$mode} Else {"Release"} + +$qtverSplit1, $qtverSplit2 ,$qtverSplit3 = $qtver.Split('.') +$qtMsvcDir = If((([int]$qtverSplit1) -ge 6) -OR ( (([int]$qtverSplit1) -eq 5) -AND (([int]$qtverSplit2) -ge 15))){"msvc2019_64"} Else{"msvc2017_64"} + +$QtDir = "C:\Qt\$qtver\$qtMsvcDir" + +$ClientDir = split-path -parent $MyInvocation.MyCommand.Definition + +$OutDir = $ClientDir + "\x64\" + $mode +If(!(test-path $OutDir)) { New-Item -ItemType directory -Path $OutDir -Force } + +if (!$daemonDir) { $daemonDir = $ClientDir + '\..\daemon' } +if (!$lrcDir) { $lrcDir = $ClientDir + '\..\lrc' } + +write-host "********************************************************************************" -ForegroundColor Magenta +write-host "using daemonDir: " $daemonDir -ForegroundColor Magenta +write-host "using lrcDir: " $lrcDir -ForegroundColor Magenta +write-host "using QtDir: " $QtDir -ForegroundColor Magenta +write-host "********************************************************************************" -ForegroundColor Magenta + +# dependency bin files and misc +$FilesToCopy = @( + "$daemonDir\contrib\build\ffmpeg\Build\win32\x64\bin\avcodec-58.dll", + "$daemonDir\contrib\build\ffmpeg\Build\win32\x64\bin\avutil-56.dll", + "$daemonDir\contrib\build\ffmpeg\Build\win32\x64\bin\avformat-58.dll", + "$daemonDir\contrib\build\ffmpeg\Build\win32\x64\bin\avdevice-58.dll", + "$daemonDir\contrib\build\ffmpeg\Build\win32\x64\bin\swresample-3.dll", + "$daemonDir\contrib\build\ffmpeg\Build\win32\x64\bin\swscale-5.dll", + "$daemonDir\contrib\build\ffmpeg\Build\win32\x64\bin\avfilter-7.dll", + "$daemonDir\contrib\build\openssl\out32dll\libeay32.dll", + "$daemonDir\contrib\build\openssl\out32dll\ssleay32.dll", + "$ClientDir\qt.conf", + "$ClientDir\images\jami.ico", + "$ClientDir\License.rtf" + ) +foreach ($i in $FilesToCopy) { + write-host "copying: " $i " => " $OutDir -ForegroundColor Cyan + Copy-Item -Path $i -Recurse -Destination $OutDir -Force -Container +} + +############ +# qt +############ +$windeployqt = "$QtDir\bin\windeployqt.exe --qmldir $ClientDir\src --release $OutDir\Jami.exe" +iex $windeployqt + +# ringtones +$CopyDir = $OutDir + "\ringtones" +If(!(test-path $CopyDir)) { New-Item -ItemType directory -Path $CopyDir -Force } +$RingtonePath = "$ClientDir\..\daemon\ringtones" +write-host "copying ringtones..." +Get-ChildItem -Path $RingtonePath -Include *.ul, *.ogg, *.wav, *.opus -Recurse | ForEach-Object { + write-host "copying ringtone: " $_.FullName " => " $CopyDir -ForegroundColor Cyan + Copy-Item -Path $_.FullName -Destination $CopyDir -Force –Recurse +} + +# qt translations +$lrelease = "$QtDir\bin\lrelease.exe" + +# lrc translations +$lrcTSPath = "$lrcDir\translations" +Get-ChildItem -Path $lrcTSPath -Include *.ts -Recurse | ForEach-Object { + & $lrelease $_.FullName +} +$CopyDir = $OutDir + "\share\libringclient\translations" +If(!(test-path $CopyDir)) { New-Item -ItemType directory -Path $CopyDir -Force } +write-host "copying lrc translations..." +Get-ChildItem -Path $lrcTSPath -Include *.qm -Recurse | ForEach-Object { + write-host "copying translation file: " $_.FullName " => " $CopyDir -ForegroundColor Cyan + Copy-Item -Path $_.FullName -Destination $CopyDir -Force –Recurse +} + +# client translations +$clientTSPath = "$ClientDir\translations" +Get-ChildItem -Path $clientTSPath -Include *.ts -Recurse | ForEach-Object { + & $lrelease $_.FullName +} +$CopyDir = $OutDir + "\share\ring\translations" +If(!(test-path $CopyDir)) { New-Item -ItemType directory -Path $CopyDir -Force } +write-host "copying client translations..." +Get-ChildItem -Path $clientTSPath -Include *.qm -Recurse | ForEach-Object { + write-host "copying translation file: " $_.FullName " => " $CopyDir -ForegroundColor Cyan + Copy-Item -Path $_.FullName -Destination $CopyDir -Force –Recurse +} + +write-host "copy completed" -NoNewline -ForegroundColor Green \ No newline at end of file diff --git a/ico.rc b/ico.rc new file mode 100644 index 00000000..ad48aa51 --- /dev/null +++ b/ico.rc @@ -0,0 +1 @@ +IDI_ICON1 ICON DISCARDABLE "images/jami.ico" diff --git a/images/FontAwesome.otf b/images/FontAwesome.otf new file mode 100644 index 00000000..401ec0f3 Binary files /dev/null and b/images/FontAwesome.otf differ diff --git a/images/ajax-loader.gif b/images/ajax-loader.gif new file mode 100644 index 00000000..f2a1bc0c Binary files /dev/null and b/images/ajax-loader.gif differ diff --git a/images/default_avatar_overlay.svg b/images/default_avatar_overlay.svg new file mode 100644 index 00000000..43cf56b5 --- /dev/null +++ b/images/default_avatar_overlay.svg @@ -0,0 +1,106 @@ + + + + + + + + + + + + + + + + image/svg+xml + + + + + + + + + + + + + + diff --git a/images/icons/av_icons/delete-24px.svg b/images/icons/av_icons/delete-24px.svg new file mode 100644 index 00000000..47e4e302 --- /dev/null +++ b/images/icons/av_icons/delete-24px.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/images/icons/av_icons/fiber_manual_record-24px.svg b/images/icons/av_icons/fiber_manual_record-24px.svg new file mode 100644 index 00000000..7ba3488b --- /dev/null +++ b/images/icons/av_icons/fiber_manual_record-24px.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/images/icons/av_icons/mic-24px.svg b/images/icons/av_icons/mic-24px.svg new file mode 100644 index 00000000..033bdee7 --- /dev/null +++ b/images/icons/av_icons/mic-24px.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/images/icons/av_icons/pause-24px.svg b/images/icons/av_icons/pause-24px.svg new file mode 100644 index 00000000..a82cdb69 --- /dev/null +++ b/images/icons/av_icons/pause-24px.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/images/icons/av_icons/play_circle_outline-24px.svg b/images/icons/av_icons/play_circle_outline-24px.svg new file mode 100644 index 00000000..bfba42d9 --- /dev/null +++ b/images/icons/av_icons/play_circle_outline-24px.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/images/icons/av_icons/re-record-24px.svg b/images/icons/av_icons/re-record-24px.svg new file mode 100644 index 00000000..db13333a --- /dev/null +++ b/images/icons/av_icons/re-record-24px.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/images/icons/av_icons/send-24px.svg b/images/icons/av_icons/send-24px.svg new file mode 100644 index 00000000..a90777f6 --- /dev/null +++ b/images/icons/av_icons/send-24px.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/images/icons/av_icons/stop-24px-red.svg b/images/icons/av_icons/stop-24px-red.svg new file mode 100644 index 00000000..1ec9ca99 --- /dev/null +++ b/images/icons/av_icons/stop-24px-red.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/images/icons/av_icons/stop-24px.svg b/images/icons/av_icons/stop-24px.svg new file mode 100644 index 00000000..7d18eed3 --- /dev/null +++ b/images/icons/av_icons/stop-24px.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/images/icons/baseline-camera_alt-24px.svg b/images/icons/baseline-camera_alt-24px.svg new file mode 100644 index 00000000..83479645 --- /dev/null +++ b/images/icons/baseline-camera_alt-24px.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/images/icons/baseline-close-24px.svg b/images/icons/baseline-close-24px.svg new file mode 100644 index 00000000..dea86781 --- /dev/null +++ b/images/icons/baseline-close-24px.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/images/icons/baseline-desktop_windows-24px.svg b/images/icons/baseline-desktop_windows-24px.svg new file mode 100644 index 00000000..f56c4759 --- /dev/null +++ b/images/icons/baseline-desktop_windows-24px.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/images/icons/baseline-done-24px.svg b/images/icons/baseline-done-24px.svg new file mode 100644 index 00000000..8790bcc1 --- /dev/null +++ b/images/icons/baseline-done-24px.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/images/icons/baseline-error_outline-24px.svg b/images/icons/baseline-error_outline-24px.svg new file mode 100644 index 00000000..39062fa7 --- /dev/null +++ b/images/icons/baseline-error_outline-24px.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/images/icons/baseline-people-24px.svg b/images/icons/baseline-people-24px.svg new file mode 100644 index 00000000..6bcb8591 --- /dev/null +++ b/images/icons/baseline-people-24px.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/images/icons/baseline-refresh-24px.svg b/images/icons/baseline-refresh-24px.svg new file mode 100644 index 00000000..f1ad30d2 --- /dev/null +++ b/images/icons/baseline-refresh-24px.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/images/icons/extension_24dp.svg b/images/icons/extension_24dp.svg new file mode 100644 index 00000000..057bf7f3 --- /dev/null +++ b/images/icons/extension_24dp.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/images/icons/ic_add_black_18dp_2x.png b/images/icons/ic_add_black_18dp_2x.png new file mode 100644 index 00000000..6f33be6b Binary files /dev/null and b/images/icons/ic_add_black_18dp_2x.png differ diff --git a/images/icons/ic_arrow_back_24px.svg b/images/icons/ic_arrow_back_24px.svg new file mode 100644 index 00000000..3a735d8a --- /dev/null +++ b/images/icons/ic_arrow_back_24px.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/images/icons/ic_arrow_back_white_24dp.png b/images/icons/ic_arrow_back_white_24dp.png new file mode 100644 index 00000000..ce5b878b Binary files /dev/null and b/images/icons/ic_arrow_back_white_24dp.png differ diff --git a/images/icons/ic_arrow_drop_down_black_18dp_2x.png b/images/icons/ic_arrow_drop_down_black_18dp_2x.png new file mode 100644 index 00000000..ec71509f Binary files /dev/null and b/images/icons/ic_arrow_drop_down_black_18dp_2x.png differ diff --git a/images/icons/ic_arrow_drop_down_black_9dp_2x.png b/images/icons/ic_arrow_drop_down_black_9dp_2x.png new file mode 100644 index 00000000..9ccea133 Binary files /dev/null and b/images/icons/ic_arrow_drop_down_black_9dp_2x.png differ diff --git a/images/icons/ic_arrow_drop_up_black_18dp_2x.png b/images/icons/ic_arrow_drop_up_black_18dp_2x.png new file mode 100644 index 00000000..65b14e07 Binary files /dev/null and b/images/icons/ic_arrow_drop_up_black_18dp_2x.png differ diff --git a/images/icons/ic_arrow_drop_up_black_9dp_2x.png b/images/icons/ic_arrow_drop_up_black_9dp_2x.png new file mode 100644 index 00000000..7c319760 Binary files /dev/null and b/images/icons/ic_arrow_drop_up_black_9dp_2x.png differ diff --git a/images/icons/ic_arrow_forward_white_48dp_2x.png b/images/icons/ic_arrow_forward_white_48dp_2x.png new file mode 100644 index 00000000..5e93f886 Binary files /dev/null and b/images/icons/ic_arrow_forward_white_48dp_2x.png differ diff --git a/images/icons/ic_arrow_tab_next_black_9dp_2x.png b/images/icons/ic_arrow_tab_next_black_9dp_2x.png new file mode 100644 index 00000000..62e6238e Binary files /dev/null and b/images/icons/ic_arrow_tab_next_black_9dp_2x.png differ diff --git a/images/icons/ic_arrow_tab_previous_black_9dp_2x.png b/images/icons/ic_arrow_tab_previous_black_9dp_2x.png new file mode 100644 index 00000000..25769dad Binary files /dev/null and b/images/icons/ic_arrow_tab_previous_black_9dp_2x.png differ diff --git a/images/icons/ic_baseline-search-24px.svg b/images/icons/ic_baseline-search-24px.svg new file mode 100644 index 00000000..19c9df70 --- /dev/null +++ b/images/icons/ic_baseline-search-24px.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/images/icons/ic_block_24px.svg b/images/icons/ic_block_24px.svg new file mode 100644 index 00000000..8032acfd --- /dev/null +++ b/images/icons/ic_block_24px.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/images/icons/ic_call_transfer_white_24px.png b/images/icons/ic_call_transfer_white_24px.png new file mode 100644 index 00000000..a43dbb4b Binary files /dev/null and b/images/icons/ic_call_transfer_white_24px.png differ diff --git a/images/icons/ic_chat_black_24dp_2x.png b/images/icons/ic_chat_black_24dp_2x.png new file mode 100644 index 00000000..e9e92e5f Binary files /dev/null and b/images/icons/ic_chat_black_24dp_2x.png differ diff --git a/images/icons/ic_chat_white_24dp.png b/images/icons/ic_chat_white_24dp.png new file mode 100644 index 00000000..ace0bef3 Binary files /dev/null and b/images/icons/ic_chat_white_24dp.png differ diff --git a/images/icons/ic_check_white_18dp_2x.png b/images/icons/ic_check_white_18dp_2x.png new file mode 100644 index 00000000..729f2901 Binary files /dev/null and b/images/icons/ic_check_white_18dp_2x.png differ diff --git a/images/icons/ic_clear_24px.svg b/images/icons/ic_clear_24px.svg new file mode 100644 index 00000000..dea86781 --- /dev/null +++ b/images/icons/ic_clear_24px.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/images/icons/ic_close_black_24dp.png b/images/icons/ic_close_black_24dp.png new file mode 100644 index 00000000..3f5c070f Binary files /dev/null and b/images/icons/ic_close_black_24dp.png differ diff --git a/images/icons/ic_close_white_24dp.png b/images/icons/ic_close_white_24dp.png new file mode 100644 index 00000000..b7c7ffd0 Binary files /dev/null and b/images/icons/ic_close_white_24dp.png differ diff --git a/images/icons/ic_content_copy.svg b/images/icons/ic_content_copy.svg new file mode 100644 index 00000000..f23e8f28 --- /dev/null +++ b/images/icons/ic_content_copy.svg @@ -0,0 +1,60 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/images/icons/ic_delete_black_18dp_2x.png b/images/icons/ic_delete_black_18dp_2x.png new file mode 100644 index 00000000..2acd0013 Binary files /dev/null and b/images/icons/ic_delete_black_18dp_2x.png differ diff --git a/images/icons/ic_done_white_24dp.png b/images/icons/ic_done_white_24dp.png new file mode 100644 index 00000000..3b2b65d2 Binary files /dev/null and b/images/icons/ic_done_white_24dp.png differ diff --git a/images/icons/ic_exit_full_screen_black.png b/images/icons/ic_exit_full_screen_black.png new file mode 100644 index 00000000..964dd002 Binary files /dev/null and b/images/icons/ic_exit_full_screen_black.png differ diff --git a/images/icons/ic_folder_black_18dp_2x.png b/images/icons/ic_folder_black_18dp_2x.png new file mode 100644 index 00000000..fceeb677 Binary files /dev/null and b/images/icons/ic_folder_black_18dp_2x.png differ diff --git a/images/icons/ic_full_screen_black.png b/images/icons/ic_full_screen_black.png new file mode 100644 index 00000000..906ca1e4 Binary files /dev/null and b/images/icons/ic_full_screen_black.png differ diff --git a/images/icons/ic_group_add_white_24dp.png b/images/icons/ic_group_add_white_24dp.png new file mode 100644 index 00000000..a769931c Binary files /dev/null and b/images/icons/ic_group_add_white_24dp.png differ diff --git a/images/icons/ic_hide_password.png b/images/icons/ic_hide_password.png new file mode 100644 index 00000000..ccad190e Binary files /dev/null and b/images/icons/ic_hide_password.png differ diff --git a/images/icons/ic_high_quality_white_24dp.png b/images/icons/ic_high_quality_white_24dp.png new file mode 100644 index 00000000..6d2d87d2 Binary files /dev/null and b/images/icons/ic_high_quality_white_24dp.png differ diff --git a/images/icons/ic_mic_off_white_24dp.png b/images/icons/ic_mic_off_white_24dp.png new file mode 100644 index 00000000..bb7915f3 Binary files /dev/null and b/images/icons/ic_mic_off_white_24dp.png differ diff --git a/images/icons/ic_mic_white_24dp.png b/images/icons/ic_mic_white_24dp.png new file mode 100644 index 00000000..5917157b Binary files /dev/null and b/images/icons/ic_mic_white_24dp.png differ diff --git a/images/icons/ic_pause_white_100px.png b/images/icons/ic_pause_white_100px.png new file mode 100644 index 00000000..fcf21884 Binary files /dev/null and b/images/icons/ic_pause_white_100px.png differ diff --git a/images/icons/ic_pause_white_24dp.png b/images/icons/ic_pause_white_24dp.png new file mode 100644 index 00000000..f49aed75 Binary files /dev/null and b/images/icons/ic_pause_white_24dp.png differ diff --git a/images/icons/ic_person_add_black_24dp_2x.png b/images/icons/ic_person_add_black_24dp_2x.png new file mode 100644 index 00000000..f3e8931b Binary files /dev/null and b/images/icons/ic_person_add_black_24dp_2x.png differ diff --git a/images/icons/ic_person_add_white_24dp.png b/images/icons/ic_person_add_white_24dp.png new file mode 100644 index 00000000..7e7c289d Binary files /dev/null and b/images/icons/ic_person_add_white_24dp.png differ diff --git a/images/icons/ic_phone_24px.svg b/images/icons/ic_phone_24px.svg new file mode 100644 index 00000000..9385a7bf --- /dev/null +++ b/images/icons/ic_phone_24px.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/images/icons/ic_photo_camera_white_24dp_2x.png b/images/icons/ic_photo_camera_white_24dp_2x.png new file mode 100644 index 00000000..be9fb226 Binary files /dev/null and b/images/icons/ic_photo_camera_white_24dp_2x.png differ diff --git a/images/icons/ic_play_white_24dp.png b/images/icons/ic_play_white_24dp.png new file mode 100644 index 00000000..d7768701 Binary files /dev/null and b/images/icons/ic_play_white_24dp.png differ diff --git a/images/icons/ic_send_24px.svg b/images/icons/ic_send_24px.svg new file mode 100644 index 00000000..4b8cef68 --- /dev/null +++ b/images/icons/ic_send_24px.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/images/icons/ic_send_white_24dp.png b/images/icons/ic_send_white_24dp.png new file mode 100644 index 00000000..ef59e776 Binary files /dev/null and b/images/icons/ic_send_white_24dp.png differ diff --git a/images/icons/ic_settings_white_48dp_2x.png b/images/icons/ic_settings_white_48dp_2x.png new file mode 100644 index 00000000..507c5edd Binary files /dev/null and b/images/icons/ic_settings_white_48dp_2x.png differ diff --git a/images/icons/ic_share_black_48dp_2x.png b/images/icons/ic_share_black_48dp_2x.png new file mode 100644 index 00000000..5a8544ce Binary files /dev/null and b/images/icons/ic_share_black_48dp_2x.png differ diff --git a/images/icons/ic_show_password.png b/images/icons/ic_show_password.png new file mode 100644 index 00000000..2a665578 Binary files /dev/null and b/images/icons/ic_show_password.png differ diff --git a/images/icons/ic_video_call_24px.svg b/images/icons/ic_video_call_24px.svg new file mode 100644 index 00000000..e062c7f3 --- /dev/null +++ b/images/icons/ic_video_call_24px.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/images/icons/ic_videocam_off_white_24dp.png b/images/icons/ic_videocam_off_white_24dp.png new file mode 100644 index 00000000..5d540589 Binary files /dev/null and b/images/icons/ic_videocam_off_white_24dp.png differ diff --git a/images/icons/ic_videocam_white.png b/images/icons/ic_videocam_white.png new file mode 100644 index 00000000..44c28e2f Binary files /dev/null and b/images/icons/ic_videocam_white.png differ diff --git a/images/icons/ic_voicemail_black_24dp_2x_.png b/images/icons/ic_voicemail_black_24dp_2x_.png new file mode 100644 index 00000000..dfd0ea06 Binary files /dev/null and b/images/icons/ic_voicemail_black_24dp_2x_.png differ diff --git a/images/icons/ic_voicemail_white_24dp_2x.png b/images/icons/ic_voicemail_white_24dp_2x.png new file mode 100644 index 00000000..59126d70 Binary files /dev/null and b/images/icons/ic_voicemail_white_24dp_2x.png differ diff --git a/images/icons/icon-keypad-24-2x.png b/images/icons/icon-keypad-24-2x.png new file mode 100644 index 00000000..2b84863e Binary files /dev/null and b/images/icons/icon-keypad-24-2x.png differ diff --git a/images/icons/icon-keypad-24.png b/images/icons/icon-keypad-24.png new file mode 100644 index 00000000..2abc9be8 Binary files /dev/null and b/images/icons/icon-keypad-24.png differ diff --git a/images/icons/info-24px.svg b/images/icons/info-24px.svg new file mode 100644 index 00000000..f8aba4cd --- /dev/null +++ b/images/icons/info-24px.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/images/icons/outline-info-24px.svg b/images/icons/outline-info-24px.svg new file mode 100644 index 00000000..ab9cff72 --- /dev/null +++ b/images/icons/outline-info-24px.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/images/icons/round-add-24px.svg b/images/icons/round-add-24px.svg new file mode 100644 index 00000000..a2fcb8eb --- /dev/null +++ b/images/icons/round-add-24px.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/images/icons/round-add_a_photo-24px.svg b/images/icons/round-add_a_photo-24px.svg new file mode 100644 index 00000000..522c3351 --- /dev/null +++ b/images/icons/round-add_a_photo-24px.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/images/icons/round-arrow_drop_down-24px.svg b/images/icons/round-arrow_drop_down-24px.svg new file mode 100644 index 00000000..49addb23 --- /dev/null +++ b/images/icons/round-arrow_drop_down-24px.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/images/icons/round-arrow_drop_up-24px.svg b/images/icons/round-arrow_drop_up-24px.svg new file mode 100644 index 00000000..f5477aec --- /dev/null +++ b/images/icons/round-arrow_drop_up-24px.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/images/icons/round-arrow_right-24px.svg b/images/icons/round-arrow_right-24px.svg new file mode 100644 index 00000000..81124fad --- /dev/null +++ b/images/icons/round-arrow_right-24px.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/images/icons/round-check_circle-24px.svg b/images/icons/round-check_circle-24px.svg new file mode 100644 index 00000000..7466a897 --- /dev/null +++ b/images/icons/round-check_circle-24px.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/images/icons/round-close-24px.svg b/images/icons/round-close-24px.svg new file mode 100644 index 00000000..e7261bc0 --- /dev/null +++ b/images/icons/round-close-24px.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/images/icons/round-edit-24px.svg b/images/icons/round-edit-24px.svg new file mode 100644 index 00000000..8d6bc172 --- /dev/null +++ b/images/icons/round-edit-24px.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/images/icons/round-error-24px.svg b/images/icons/round-error-24px.svg new file mode 100644 index 00000000..3daa4785 --- /dev/null +++ b/images/icons/round-error-24px.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/images/icons/round-folder-24px.svg b/images/icons/round-folder-24px.svg new file mode 100644 index 00000000..4f02e223 --- /dev/null +++ b/images/icons/round-folder-24px.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/images/icons/round-remove_circle-24px.svg b/images/icons/round-remove_circle-24px.svg new file mode 100644 index 00000000..9413863e --- /dev/null +++ b/images/icons/round-remove_circle-24px.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/images/icons/round-save_alt-24px.svg b/images/icons/round-save_alt-24px.svg new file mode 100644 index 00000000..07b2cb52 --- /dev/null +++ b/images/icons/round-save_alt-24px.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/images/icons/round-settings-24px.svg b/images/icons/round-settings-24px.svg new file mode 100644 index 00000000..fd34fc46 --- /dev/null +++ b/images/icons/round-settings-24px.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/images/icons/round-undo-24px.svg b/images/icons/round-undo-24px.svg new file mode 100644 index 00000000..c0e92414 --- /dev/null +++ b/images/icons/round-undo-24px.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/images/icons/settings_backup_restore-black-18dp.svg b/images/icons/settings_backup_restore-black-18dp.svg new file mode 100644 index 00000000..f61d2745 --- /dev/null +++ b/images/icons/settings_backup_restore-black-18dp.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/images/jami.ico b/images/jami.ico new file mode 100644 index 00000000..468e452e Binary files /dev/null and b/images/jami.ico differ diff --git a/images/jami.png b/images/jami.png new file mode 100644 index 00000000..aef46d27 Binary files /dev/null and b/images/jami.png differ diff --git a/images/jami_eclipse_spinner.gif b/images/jami_eclipse_spinner.gif new file mode 100644 index 00000000..7c66d3ff Binary files /dev/null and b/images/jami_eclipse_spinner.gif differ diff --git a/images/jami_rolling_spinner.gif b/images/jami_rolling_spinner.gif new file mode 100644 index 00000000..63ff54ad Binary files /dev/null and b/images/jami_rolling_spinner.gif differ diff --git a/images/logo-jami-standard-coul.png b/images/logo-jami-standard-coul.png new file mode 100644 index 00000000..0352b55b Binary files /dev/null and b/images/logo-jami-standard-coul.png differ diff --git a/images/qrcode.png b/images/qrcode.png new file mode 100644 index 00000000..89d72e1a Binary files /dev/null and b/images/qrcode.png differ diff --git a/images/spike.png b/images/spike.png new file mode 100644 index 00000000..1f039270 Binary files /dev/null and b/images/spike.png differ diff --git a/images/waiting.gif b/images/waiting.gif new file mode 100644 index 00000000..ba2fbbcf Binary files /dev/null and b/images/waiting.gif differ diff --git a/jami-qt.pro b/jami-qt.pro new file mode 100644 index 00000000..13a17562 --- /dev/null +++ b/jami-qt.pro @@ -0,0 +1,186 @@ +win32-msvc { + TARGET = Jami + TEMPLATE = vcapp + + QT += core winextras qml quickcontrols2 quick xml multimedia network webengine svg sql + + CONFIG += suppress_vcproj_warnings c++17 qtquickcompiler + + QTQUICK_COMPILER_SKIPPED_RESOURCES += ./ressources.qrc + + # compiler options + QMAKE_CXXFLAGS += /wd"4068" /wd"4099" /wd"4189" /wd"4267" /wd"4577" /wd"4467" /wd"4715" /wd"4828" + QMAKE_CXXFLAGS += /MP /GS /W3 /Gy /Zc:wchar_t /Zi /Gm- /O2 /Zc:inline /fp:precise /errorReport:prompt + QMAKE_CXXFLAGS += /Gd /Oi /MD /std:c++17 /FC /EHsc /nologo /sdl + + # linker options + QMAKE_LFLAGS+= /ignore:4006,4049,4078,4098 /FORCE:MULTIPLE /INCREMENTAL:NO /Debug /LTCG /NODEFAULTLIB:LIBCMT + + # preprocessor defines + DEFINES += UNICODE QT_NO_DEBUG NDEBUG + + # dependencies + LRC= ../lrc + DRING= ../daemon + QRENCODE= qrencode-win32/qrencode-win32 + + # client deps + INCLUDEPATH += $${QRENCODE} + LIBS += $${QRENCODE}/vc8/qrcodelib/x64/Release-Lib/qrcodelib.lib + + # lrc + INCLUDEPATH += $${LRC}/src/ + LIBS += $${LRC}/msvc/release/ringclient_static.lib + LIBS += $${LRC}/msvc/src/qtwrapper/Release/qtwrapper.lib + + # daemon + INCLUDEPATH += ../daemon/contrib/msvc/include/ + LIBS += $${DRING}/build-local/x64/ReleaseLib_win32/bin/dring.lib + LIBS += $${DRING}/contrib/msvc/lib/x64/libgnutls.lib + + # windows system libs + LIBS += Shell32.lib Ole32.lib Advapi32.lib Shlwapi.lib User32.lib Gdi32.lib Crypt32.lib Strmiids.lib + + # output paths + OBJECTS_DIR = obj/.obj + MOC_DIR = obj/.moc + RCC_DIR = obj/.rcc + UI_DIR = obj/.ui + + # ReleaseCompile config + contains(CONFIG, ReleaseCompile) { + CONFIG(ReleaseCompile) { + message(ReleaseCompile config enabled) + Release: DEFINES += COMPILE_ONLY + } + } + + # beta config + contains(CONFIG, Beta) { + CONFIG(Beta) { + message(Beta config enabled) + Release: DESTDIR = x64/Beta + Release: DEFINES += BETA + } + } else { + Release: DESTDIR = x64/Release + } + Debug: DESTDIR = x64/Debug + + # qt dir + QMAKE_INCDIR_QT=$(QTDIR)\include + QMAKE_LIBDIR=$(QTDIR)\lib + QMAKE_MOC=$(QTDIR)\bin\moc.exe + QMAKE_QMAKE=$(QTDIR)\bin\qmake.exe + + # exe icons + Release: RC_FILE = ico.rc +} + +unix { + TARGET = jami-qt + TEMPLATE = app + + QT += quick quickwidgets widgets xml multimedia multimediawidgets network webenginewidgets svg quickcontrols2 webengine webenginecore sql dbus + + #check Qt version + QT_VERSION = $$[QT_VERSION] + QT_VERSION = $$split(QT_VERSION, ".") + QT_VER_MAJ = $$member(QT_VERSION, 0) + QT_VER_MIN = $$member(QT_VERSION, 1) + + lessThan(QT_VER_MIN, 12) { + QMAKE_CXXFLAGS += -std=c++17 + } + greaterThan(QT_VER_MIN, 12) | equals(QT_VER_MIN, 12) { + CONFIG += c++17 + } + + isEmpty(LRC) { LRC=../../install/lrc/ } + + INCLUDEPATH += $${LRC}/include/libringclient + INCLUDEPATH += $${LRC}/include + INCLUDEPATH += ../src + + LIBS += -L$${LRC}/lib -lringclient + LIBS += -lqrencode +} + +# Input +HEADERS += ./src/smartlistmodel.h \ + ./src/utils.h \ + ./src/bannedlistmodel.h \ + ./src/version.h \ + ./src/accountlistmodel.h \ + ./src/runguard.h \ + ./src/lrcinstance.h \ + ./src/globalsystemtray.h \ + ./src/settingskey.h \ + ./src/webchathelpers.h \ + ./src/pixbufmanipulator.h \ + ./src/rendermanager.h \ + ./src/connectivitymonitor.h \ + ./src/jamiavatartheme.h \ + ./src/mainapplication.h \ + ./src/qrimageprovider.h \ + ./src/messagesadapter.h \ + ./src/accountadapter.h \ + ./src/tintedbuttonimageprovider.h \ + ./src/calladapter.h \ + ./src/conversationsadapter.h \ + ./src/distantrenderer.h \ + ./src/previewrenderer.h \ + ./src/qmladapterbase.h \ + ./src/avadapter.h \ + ./src/contactadapter.h \ + ./src/settingsadaptor.h \ + ./src/deviceitemlistmodel.h \ + ./src/pluginitemlistmodel.h \ + ./src/preferenceitemlistmodel.h \ + ./src/audiocodeclistmodel.h \ + ./src/videocodeclistmodel.h \ + ./src/accountstomigratelistmodel.h \ + ./src/clientwrapper.h \ + ./src/audioinputdevicemodel.h \ + ./src/videoinputdevicemodel.h \ + ./src/audiooutputdevicemodel.h \ + ./src/videoformatfpsmodel.h \ + ./src/videoformatresolutionmodel.h \ + ./src/audiomanagerlistmodel.h +SOURCES += ./src/bannedlistmodel.cpp \ + ./src/accountlistmodel.cpp \ + ./src/runguard.cpp \ + ./src/webchathelpers.cpp \ + ./src/main.cpp \ + ./src/globalsystemtray.cpp \ + ./src/smartlistmodel.cpp \ + ./src/utils.cpp \ + ./src/pixbufmanipulator.cpp \ + ./src/rendermanager.cpp \ + ./src/connectivitymonitor.cpp \ + ./src/mainapplication.cpp \ + ./src/messagesadapter.cpp \ + ./src/accountadapter.cpp \ + ./src/calladapter.cpp \ + ./src/conversationsadapter.cpp \ + ./src/distantrenderer.cpp \ + ./src/previewrenderer.cpp \ + ./src/qmladapterbase.cpp \ + ./src/avadapter.cpp \ + ./src/contactadapter.cpp \ + ./src/settingsadaptor.cpp \ + ./src/deviceitemlistmodel.cpp \ + ./src/pluginitemlistmodel.cpp \ + ./src/preferenceitemlistmodel.cpp \ + ./src/audiocodeclistmodel.cpp \ + ./src/videocodeclistmodel.cpp \ + ./src/accountstomigratelistmodel.cpp \ + ./src/clientwrapper.cpp \ + ./src/audioinputdevicemodel.cpp \ + ./src/videoinputdevicemodel.cpp \ + ./src/audiooutputdevicemodel.cpp \ + ./src/videoformatfpsmodel.cpp \ + ./src/videoformatresolutionmodel.cpp \ + ./src/audiomanagerlistmodel.cpp +RESOURCES += ./ressources.qrc \ + ./qml.qrc diff --git a/jami-qt.sln b/jami-qt.sln new file mode 100644 index 00000000..1ae2b969 --- /dev/null +++ b/jami-qt.sln @@ -0,0 +1,636 @@ +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio Version 16 +VisualStudioVersion = 16.0.29613.14 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "ring-daemon", "..\daemon\build-local\ring-daemon.vcxproj", "{1CA4822C-F599-3879-A78F-332D823E4871}" + ProjectSection(ProjectDependencies) = postProject + {2BB84911-C1B4-4747-B93D-36AA82CC5031} = {2BB84911-C1B4-4747-B93D-36AA82CC5031} + {A5D9AA24-08ED-48B9-BD65-F0A25E96BFC4} = {A5D9AA24-08ED-48B9-BD65-F0A25E96BFC4} + {B82CDD25-6903-430E-BD38-D8129A2015C1} = {B82CDD25-6903-430E-BD38-D8129A2015C1} + {FE07F272-AE7F-4549-9E9F-EF9B80CB1693} = {FE07F272-AE7F-4549-9E9F-EF9B80CB1693} + {7FDE3880-A4AB-49E3-B439-EBEF0A0C7A65} = {7FDE3880-A4AB-49E3-B439-EBEF0A0C7A65} + {855DC8C0-D3E9-4A2E-AE47-116605A7BC9B} = {855DC8C0-D3E9-4A2E-AE47-116605A7BC9B} + {4B5945CD-0CB3-49AA-A7FF-7612D93F82C0} = {4B5945CD-0CB3-49AA-A7FF-7612D93F82C0} + {711397CE-E5D5-467D-9457-8716C047E50C} = {711397CE-E5D5-467D-9457-8716C047E50C} + {B8719FD5-E8A6-4A36-943C-891D07F5DD21} = {B8719FD5-E8A6-4A36-943C-891D07F5DD21} + {DA0E03ED-53A7-4050-8A85-90541C5509F8} = {DA0E03ED-53A7-4050-8A85-90541C5509F8} + {9CA0FDFB-2172-41FC-B7F1-5CE915EDCB37} = {9CA0FDFB-2172-41FC-B7F1-5CE915EDCB37} + EndProjectSection +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "ringclient_static", "..\lrc\msvc\ringclient_static.vcxproj", "{774F1C61-6659-36E6-9519-17A753890576}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "qtwrapper", "..\lrc\msvc\src\qtwrapper\qtwrapper.vcxproj", "{2CFF20AA-9341-3564-A044-C38E70D5372A}" + ProjectSection(ProjectDependencies) = postProject + {1CA4822C-F599-3879-A78F-332D823E4871} = {1CA4822C-F599-3879-A78F-332D823E4871} + EndProjectSection +EndProject +Project("{930C7802-8A8C-48F9-8165-68863BCCD9DD}") = "JamiInstaller", "JamiInstaller\JamiInstaller.wixproj", "{DBBFBC55-1C20-4D21-AE3B-6E8B14C4FE48}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "daemon", "daemon", "{B6752729-7398-46FA-9CF0-DC854C6AB8CA}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "pjnath", "..\daemon\contrib\build\pjproject\pjnath\build\pjnath.vcxproj", "{A5D9AA24-08ED-48B9-BD65-F0A25E96BFC4}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "pjproject", "pjproject", "{14A77BA7-0E23-4D8F-A74F-5D5D5583035D}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "pjmedia", "..\daemon\contrib\build\pjproject\pjmedia\build\pjmedia.vcxproj", "{7FDE3880-A4AB-49E3-B439-EBEF0A0C7A65}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "pjmedia_codec", "..\daemon\contrib\build\pjproject\pjmedia\build\pjmedia_codec.vcxproj", "{855DC8C0-D3E9-4A2E-AE47-116605A7BC9B}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "pjlib_util", "..\daemon\contrib\build\pjproject\pjlib-util\build\pjlib_util.vcxproj", "{FE07F272-AE7F-4549-9E9F-EF9B80CB1693}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "pjlib", "..\daemon\contrib\build\pjproject\pjlib\build\pjlib.vcxproj", "{DA0E03ED-53A7-4050-8A85-90541C5509F8}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "pjsip_core", "..\daemon\contrib\build\pjproject\pjsip\build\pjsip_core.vcxproj", "{2BB84911-C1B4-4747-B93D-36AA82CC5031}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "pjsua2_lib", "..\daemon\contrib\build\pjproject\pjsip\build\pjsua2_lib.vcxproj", "{B82CDD25-6903-430E-BD38-D8129A2015C1}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "pjsua_lib", "..\daemon\contrib\build\pjproject\pjsip\build\pjsua_lib.vcxproj", "{9CA0FDFB-2172-41FC-B7F1-5CE915EDCB37}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "pjsip_simple", "..\daemon\contrib\build\pjproject\pjsip\build\pjsip_simple.vcxproj", "{4B5945CD-0CB3-49AA-A7FF-7612D93F82C0}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "pjsip_ua", "..\daemon\contrib\build\pjproject\pjsip\build\pjsip_ua.vcxproj", "{B8719FD5-E8A6-4A36-943C-891D07F5DD21}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "lrc", "lrc", "{31F92F98-3580-445D-A3DA-D081B427A562}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "client", "client", "{1ECB5BD6-B3A0-4135-BA3F-48FC367B61C9}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "contrib", "contrib", "{B4FD804C-ABD9-4F54-858B-911F0119580C}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "opendht", "..\daemon\contrib\build\opendht\MSVC\opendht.vcxproj", "{711397CE-E5D5-467D-9457-8716C047E50C}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "jami-qt", "jami-qt.vcxproj", "{A1BDC12C-5DF6-3E77-9793-AB9AB5C82027}" + ProjectSection(ProjectDependencies) = postProject + {774F1C61-6659-36E6-9519-17A753890576} = {774F1C61-6659-36E6-9519-17A753890576} + EndProjectSection +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Beta|Any CPU = Beta|Any CPU + Beta|x64 = Beta|x64 + Beta|x86 = Beta|x86 + Debug|Any CPU = Debug|Any CPU + Debug|x64 = Debug|x64 + Debug|x86 = Debug|x86 + Release|Any CPU = Release|Any CPU + Release|x64 = Release|x64 + Release|x86 = Release|x86 + ReleaseCompile|Any CPU = ReleaseCompile|Any CPU + ReleaseCompile|x64 = ReleaseCompile|x64 + ReleaseCompile|x86 = ReleaseCompile|x86 + ReleaseLib_win32|Any CPU = ReleaseLib_win32|Any CPU + ReleaseLib_win32|x64 = ReleaseLib_win32|x64 + ReleaseLib_win32|x86 = ReleaseLib_win32|x86 + ReleaseLib|Any CPU = ReleaseLib|Any CPU + ReleaseLib|x64 = ReleaseLib|x64 + ReleaseLib|x86 = ReleaseLib|x86 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {1CA4822C-F599-3879-A78F-332D823E4871}.Beta|Any CPU.ActiveCfg = ReleaseLib_win32|x64 + {1CA4822C-F599-3879-A78F-332D823E4871}.Beta|Any CPU.Build.0 = ReleaseLib_win32|x64 + {1CA4822C-F599-3879-A78F-332D823E4871}.Beta|x64.ActiveCfg = ReleaseLib_win32|x64 + {1CA4822C-F599-3879-A78F-332D823E4871}.Beta|x64.Build.0 = ReleaseLib_win32|x64 + {1CA4822C-F599-3879-A78F-332D823E4871}.Beta|x86.ActiveCfg = ReleaseLib_win32|x64 + {1CA4822C-F599-3879-A78F-332D823E4871}.Beta|x86.Build.0 = ReleaseLib_win32|x64 + {1CA4822C-F599-3879-A78F-332D823E4871}.Debug|Any CPU.ActiveCfg = ReleaseLib_win32|x64 + {1CA4822C-F599-3879-A78F-332D823E4871}.Debug|Any CPU.Build.0 = ReleaseLib_win32|x64 + {1CA4822C-F599-3879-A78F-332D823E4871}.Debug|x64.ActiveCfg = ReleaseLib_win32|x64 + {1CA4822C-F599-3879-A78F-332D823E4871}.Debug|x64.Build.0 = ReleaseLib_win32|x64 + {1CA4822C-F599-3879-A78F-332D823E4871}.Debug|x86.ActiveCfg = ReleaseLib_win32|x64 + {1CA4822C-F599-3879-A78F-332D823E4871}.Debug|x86.Build.0 = ReleaseLib_win32|x64 + {1CA4822C-F599-3879-A78F-332D823E4871}.Release|Any CPU.ActiveCfg = ReleaseLib_win32|x64 + {1CA4822C-F599-3879-A78F-332D823E4871}.Release|Any CPU.Build.0 = ReleaseLib_win32|x64 + {1CA4822C-F599-3879-A78F-332D823E4871}.Release|x64.ActiveCfg = ReleaseLib_win32|x64 + {1CA4822C-F599-3879-A78F-332D823E4871}.Release|x64.Build.0 = ReleaseLib_win32|x64 + {1CA4822C-F599-3879-A78F-332D823E4871}.Release|x86.ActiveCfg = ReleaseLib_win32|x64 + {1CA4822C-F599-3879-A78F-332D823E4871}.Release|x86.Build.0 = ReleaseLib_win32|x64 + {1CA4822C-F599-3879-A78F-332D823E4871}.ReleaseCompile|Any CPU.ActiveCfg = ReleaseLib_win32|x64 + {1CA4822C-F599-3879-A78F-332D823E4871}.ReleaseCompile|Any CPU.Build.0 = ReleaseLib_win32|x64 + {1CA4822C-F599-3879-A78F-332D823E4871}.ReleaseCompile|x64.ActiveCfg = ReleaseLib_win32|x64 + {1CA4822C-F599-3879-A78F-332D823E4871}.ReleaseCompile|x64.Build.0 = ReleaseLib_win32|x64 + {1CA4822C-F599-3879-A78F-332D823E4871}.ReleaseCompile|x86.ActiveCfg = ReleaseLib_win32|x64 + {1CA4822C-F599-3879-A78F-332D823E4871}.ReleaseCompile|x86.Build.0 = ReleaseLib_win32|x64 + {1CA4822C-F599-3879-A78F-332D823E4871}.ReleaseLib_win32|Any CPU.ActiveCfg = ReleaseLib_win32|x64 + {1CA4822C-F599-3879-A78F-332D823E4871}.ReleaseLib_win32|x64.ActiveCfg = ReleaseLib_win32|x64 + {1CA4822C-F599-3879-A78F-332D823E4871}.ReleaseLib_win32|x64.Build.0 = ReleaseLib_win32|x64 + {1CA4822C-F599-3879-A78F-332D823E4871}.ReleaseLib_win32|x86.ActiveCfg = ReleaseLib_win32|x64 + {1CA4822C-F599-3879-A78F-332D823E4871}.ReleaseLib|Any CPU.ActiveCfg = ReleaseLib_win32|x64 + {1CA4822C-F599-3879-A78F-332D823E4871}.ReleaseLib|Any CPU.Build.0 = ReleaseLib_win32|x64 + {1CA4822C-F599-3879-A78F-332D823E4871}.ReleaseLib|x64.ActiveCfg = ReleaseLib_win32|x64 + {1CA4822C-F599-3879-A78F-332D823E4871}.ReleaseLib|x64.Build.0 = ReleaseLib_win32|x64 + {1CA4822C-F599-3879-A78F-332D823E4871}.ReleaseLib|x86.ActiveCfg = ReleaseLib_win32|x64 + {1CA4822C-F599-3879-A78F-332D823E4871}.ReleaseLib|x86.Build.0 = ReleaseLib_win32|x64 + {774F1C61-6659-36E6-9519-17A753890576}.Beta|Any CPU.ActiveCfg = Release|x64 + {774F1C61-6659-36E6-9519-17A753890576}.Beta|x64.ActiveCfg = Release|x64 + {774F1C61-6659-36E6-9519-17A753890576}.Beta|x64.Build.0 = Release|x64 + {774F1C61-6659-36E6-9519-17A753890576}.Beta|x86.ActiveCfg = Release|x64 + {774F1C61-6659-36E6-9519-17A753890576}.Debug|Any CPU.ActiveCfg = Debug|x64 + {774F1C61-6659-36E6-9519-17A753890576}.Debug|x64.ActiveCfg = Debug|x64 + {774F1C61-6659-36E6-9519-17A753890576}.Debug|x64.Build.0 = Debug|x64 + {774F1C61-6659-36E6-9519-17A753890576}.Debug|x86.ActiveCfg = Debug|x64 + {774F1C61-6659-36E6-9519-17A753890576}.Release|Any CPU.ActiveCfg = Release|x64 + {774F1C61-6659-36E6-9519-17A753890576}.Release|x64.ActiveCfg = Release|x64 + {774F1C61-6659-36E6-9519-17A753890576}.Release|x64.Build.0 = Release|x64 + {774F1C61-6659-36E6-9519-17A753890576}.Release|x86.ActiveCfg = Release|x64 + {774F1C61-6659-36E6-9519-17A753890576}.ReleaseCompile|Any CPU.ActiveCfg = Release|x64 + {774F1C61-6659-36E6-9519-17A753890576}.ReleaseCompile|Any CPU.Build.0 = Release|x64 + {774F1C61-6659-36E6-9519-17A753890576}.ReleaseCompile|x64.ActiveCfg = Release|x64 + {774F1C61-6659-36E6-9519-17A753890576}.ReleaseCompile|x64.Build.0 = Release|x64 + {774F1C61-6659-36E6-9519-17A753890576}.ReleaseCompile|x86.ActiveCfg = Release|x64 + {774F1C61-6659-36E6-9519-17A753890576}.ReleaseCompile|x86.Build.0 = Release|x64 + {774F1C61-6659-36E6-9519-17A753890576}.ReleaseLib_win32|Any CPU.ActiveCfg = RelWithDebInfo|x64 + {774F1C61-6659-36E6-9519-17A753890576}.ReleaseLib_win32|Any CPU.Build.0 = RelWithDebInfo|x64 + {774F1C61-6659-36E6-9519-17A753890576}.ReleaseLib_win32|x64.ActiveCfg = Release|x64 + {774F1C61-6659-36E6-9519-17A753890576}.ReleaseLib_win32|x64.Build.0 = Release|x64 + {774F1C61-6659-36E6-9519-17A753890576}.ReleaseLib_win32|x86.ActiveCfg = RelWithDebInfo|x64 + {774F1C61-6659-36E6-9519-17A753890576}.ReleaseLib_win32|x86.Build.0 = RelWithDebInfo|x64 + {774F1C61-6659-36E6-9519-17A753890576}.ReleaseLib|Any CPU.ActiveCfg = RelWithDebInfo|x64 + {774F1C61-6659-36E6-9519-17A753890576}.ReleaseLib|Any CPU.Build.0 = RelWithDebInfo|x64 + {774F1C61-6659-36E6-9519-17A753890576}.ReleaseLib|x64.ActiveCfg = Release|x64 + {774F1C61-6659-36E6-9519-17A753890576}.ReleaseLib|x64.Build.0 = Release|x64 + {774F1C61-6659-36E6-9519-17A753890576}.ReleaseLib|x86.ActiveCfg = MinSizeRel|x64 + {774F1C61-6659-36E6-9519-17A753890576}.ReleaseLib|x86.Build.0 = MinSizeRel|x64 + {2CFF20AA-9341-3564-A044-C38E70D5372A}.Beta|Any CPU.ActiveCfg = Release|x64 + {2CFF20AA-9341-3564-A044-C38E70D5372A}.Beta|x64.ActiveCfg = Release|x64 + {2CFF20AA-9341-3564-A044-C38E70D5372A}.Beta|x64.Build.0 = Release|x64 + {2CFF20AA-9341-3564-A044-C38E70D5372A}.Beta|x86.ActiveCfg = Release|x64 + {2CFF20AA-9341-3564-A044-C38E70D5372A}.Debug|Any CPU.ActiveCfg = Debug|x64 + {2CFF20AA-9341-3564-A044-C38E70D5372A}.Debug|x64.ActiveCfg = Debug|x64 + {2CFF20AA-9341-3564-A044-C38E70D5372A}.Debug|x64.Build.0 = Debug|x64 + {2CFF20AA-9341-3564-A044-C38E70D5372A}.Debug|x86.ActiveCfg = Debug|x64 + {2CFF20AA-9341-3564-A044-C38E70D5372A}.Release|Any CPU.ActiveCfg = Release|x64 + {2CFF20AA-9341-3564-A044-C38E70D5372A}.Release|x64.ActiveCfg = Release|x64 + {2CFF20AA-9341-3564-A044-C38E70D5372A}.Release|x64.Build.0 = Release|x64 + {2CFF20AA-9341-3564-A044-C38E70D5372A}.Release|x86.ActiveCfg = Release|x64 + {2CFF20AA-9341-3564-A044-C38E70D5372A}.ReleaseCompile|Any CPU.ActiveCfg = Release|x64 + {2CFF20AA-9341-3564-A044-C38E70D5372A}.ReleaseCompile|Any CPU.Build.0 = Release|x64 + {2CFF20AA-9341-3564-A044-C38E70D5372A}.ReleaseCompile|x64.ActiveCfg = Release|x64 + {2CFF20AA-9341-3564-A044-C38E70D5372A}.ReleaseCompile|x64.Build.0 = Release|x64 + {2CFF20AA-9341-3564-A044-C38E70D5372A}.ReleaseCompile|x86.ActiveCfg = Release|x64 + {2CFF20AA-9341-3564-A044-C38E70D5372A}.ReleaseCompile|x86.Build.0 = Release|x64 + {2CFF20AA-9341-3564-A044-C38E70D5372A}.ReleaseLib_win32|Any CPU.ActiveCfg = RelWithDebInfo|x64 + {2CFF20AA-9341-3564-A044-C38E70D5372A}.ReleaseLib_win32|Any CPU.Build.0 = RelWithDebInfo|x64 + {2CFF20AA-9341-3564-A044-C38E70D5372A}.ReleaseLib_win32|x64.ActiveCfg = Release|x64 + {2CFF20AA-9341-3564-A044-C38E70D5372A}.ReleaseLib_win32|x64.Build.0 = Release|x64 + {2CFF20AA-9341-3564-A044-C38E70D5372A}.ReleaseLib_win32|x86.ActiveCfg = RelWithDebInfo|x64 + {2CFF20AA-9341-3564-A044-C38E70D5372A}.ReleaseLib_win32|x86.Build.0 = RelWithDebInfo|x64 + {2CFF20AA-9341-3564-A044-C38E70D5372A}.ReleaseLib|Any CPU.ActiveCfg = RelWithDebInfo|x64 + {2CFF20AA-9341-3564-A044-C38E70D5372A}.ReleaseLib|Any CPU.Build.0 = RelWithDebInfo|x64 + {2CFF20AA-9341-3564-A044-C38E70D5372A}.ReleaseLib|x64.ActiveCfg = Release|x64 + {2CFF20AA-9341-3564-A044-C38E70D5372A}.ReleaseLib|x64.Build.0 = Release|x64 + {2CFF20AA-9341-3564-A044-C38E70D5372A}.ReleaseLib|x86.ActiveCfg = MinSizeRel|x64 + {2CFF20AA-9341-3564-A044-C38E70D5372A}.ReleaseLib|x86.Build.0 = MinSizeRel|x64 + {DBBFBC55-1C20-4D21-AE3B-6E8B14C4FE48}.Beta|Any CPU.ActiveCfg = Release|x64 + {DBBFBC55-1C20-4D21-AE3B-6E8B14C4FE48}.Beta|x64.ActiveCfg = Beta|x64 + {DBBFBC55-1C20-4D21-AE3B-6E8B14C4FE48}.Beta|x64.Build.0 = Beta|x64 + {DBBFBC55-1C20-4D21-AE3B-6E8B14C4FE48}.Beta|x86.ActiveCfg = Release|x64 + {DBBFBC55-1C20-4D21-AE3B-6E8B14C4FE48}.Debug|Any CPU.ActiveCfg = Beta|x64 + {DBBFBC55-1C20-4D21-AE3B-6E8B14C4FE48}.Debug|Any CPU.Build.0 = Beta|x64 + {DBBFBC55-1C20-4D21-AE3B-6E8B14C4FE48}.Debug|x64.ActiveCfg = Beta|x64 + {DBBFBC55-1C20-4D21-AE3B-6E8B14C4FE48}.Debug|x64.Build.0 = Beta|x64 + {DBBFBC55-1C20-4D21-AE3B-6E8B14C4FE48}.Debug|x86.ActiveCfg = Beta|x64 + {DBBFBC55-1C20-4D21-AE3B-6E8B14C4FE48}.Debug|x86.Build.0 = Beta|x64 + {DBBFBC55-1C20-4D21-AE3B-6E8B14C4FE48}.Release|Any CPU.ActiveCfg = Release|x64 + {DBBFBC55-1C20-4D21-AE3B-6E8B14C4FE48}.Release|x64.ActiveCfg = Release|x64 + {DBBFBC55-1C20-4D21-AE3B-6E8B14C4FE48}.Release|x64.Build.0 = Release|x64 + {DBBFBC55-1C20-4D21-AE3B-6E8B14C4FE48}.Release|x86.ActiveCfg = Release|x64 + {DBBFBC55-1C20-4D21-AE3B-6E8B14C4FE48}.ReleaseCompile|Any CPU.ActiveCfg = Release|x64 + {DBBFBC55-1C20-4D21-AE3B-6E8B14C4FE48}.ReleaseCompile|Any CPU.Build.0 = Release|x64 + {DBBFBC55-1C20-4D21-AE3B-6E8B14C4FE48}.ReleaseCompile|x64.ActiveCfg = Release|x64 + {DBBFBC55-1C20-4D21-AE3B-6E8B14C4FE48}.ReleaseCompile|x64.Build.0 = Release|x64 + {DBBFBC55-1C20-4D21-AE3B-6E8B14C4FE48}.ReleaseCompile|x86.ActiveCfg = Release|x64 + {DBBFBC55-1C20-4D21-AE3B-6E8B14C4FE48}.ReleaseCompile|x86.Build.0 = Release|x64 + {DBBFBC55-1C20-4D21-AE3B-6E8B14C4FE48}.ReleaseLib_win32|Any CPU.ActiveCfg = Release|x64 + {DBBFBC55-1C20-4D21-AE3B-6E8B14C4FE48}.ReleaseLib_win32|Any CPU.Build.0 = Release|x64 + {DBBFBC55-1C20-4D21-AE3B-6E8B14C4FE48}.ReleaseLib_win32|x64.ActiveCfg = Release|x64 + {DBBFBC55-1C20-4D21-AE3B-6E8B14C4FE48}.ReleaseLib_win32|x64.Build.0 = Release|x64 + {DBBFBC55-1C20-4D21-AE3B-6E8B14C4FE48}.ReleaseLib_win32|x86.ActiveCfg = Release|x64 + {DBBFBC55-1C20-4D21-AE3B-6E8B14C4FE48}.ReleaseLib_win32|x86.Build.0 = Release|x64 + {DBBFBC55-1C20-4D21-AE3B-6E8B14C4FE48}.ReleaseLib|Any CPU.ActiveCfg = Release|x64 + {DBBFBC55-1C20-4D21-AE3B-6E8B14C4FE48}.ReleaseLib|Any CPU.Build.0 = Release|x64 + {DBBFBC55-1C20-4D21-AE3B-6E8B14C4FE48}.ReleaseLib|x64.ActiveCfg = Release|x64 + {DBBFBC55-1C20-4D21-AE3B-6E8B14C4FE48}.ReleaseLib|x64.Build.0 = Release|x64 + {DBBFBC55-1C20-4D21-AE3B-6E8B14C4FE48}.ReleaseLib|x86.ActiveCfg = Release|x64 + {DBBFBC55-1C20-4D21-AE3B-6E8B14C4FE48}.ReleaseLib|x86.Build.0 = Release|x64 + {A5D9AA24-08ED-48B9-BD65-F0A25E96BFC4}.Beta|Any CPU.ActiveCfg = Release|Win32 + {A5D9AA24-08ED-48B9-BD65-F0A25E96BFC4}.Beta|x64.ActiveCfg = Release|x64 + {A5D9AA24-08ED-48B9-BD65-F0A25E96BFC4}.Beta|x64.Build.0 = Release|x64 + {A5D9AA24-08ED-48B9-BD65-F0A25E96BFC4}.Beta|x86.ActiveCfg = Release|Win32 + {A5D9AA24-08ED-48B9-BD65-F0A25E96BFC4}.Beta|x86.Build.0 = Release|Win32 + {A5D9AA24-08ED-48B9-BD65-F0A25E96BFC4}.Debug|Any CPU.ActiveCfg = Debug|Win32 + {A5D9AA24-08ED-48B9-BD65-F0A25E96BFC4}.Debug|x64.ActiveCfg = Debug|x64 + {A5D9AA24-08ED-48B9-BD65-F0A25E96BFC4}.Debug|x64.Build.0 = Debug|x64 + {A5D9AA24-08ED-48B9-BD65-F0A25E96BFC4}.Debug|x86.ActiveCfg = Debug|Win32 + {A5D9AA24-08ED-48B9-BD65-F0A25E96BFC4}.Debug|x86.Build.0 = Debug|Win32 + {A5D9AA24-08ED-48B9-BD65-F0A25E96BFC4}.Release|Any CPU.ActiveCfg = Release|Win32 + {A5D9AA24-08ED-48B9-BD65-F0A25E96BFC4}.Release|x64.ActiveCfg = Release|x64 + {A5D9AA24-08ED-48B9-BD65-F0A25E96BFC4}.Release|x64.Build.0 = Release|x64 + {A5D9AA24-08ED-48B9-BD65-F0A25E96BFC4}.Release|x86.ActiveCfg = Release|Win32 + {A5D9AA24-08ED-48B9-BD65-F0A25E96BFC4}.Release|x86.Build.0 = Release|Win32 + {A5D9AA24-08ED-48B9-BD65-F0A25E96BFC4}.ReleaseCompile|Any CPU.ActiveCfg = Release|ARM + {A5D9AA24-08ED-48B9-BD65-F0A25E96BFC4}.ReleaseCompile|Any CPU.Build.0 = Release|ARM + {A5D9AA24-08ED-48B9-BD65-F0A25E96BFC4}.ReleaseCompile|x64.ActiveCfg = Release|x64 + {A5D9AA24-08ED-48B9-BD65-F0A25E96BFC4}.ReleaseCompile|x64.Build.0 = Release|x64 + {A5D9AA24-08ED-48B9-BD65-F0A25E96BFC4}.ReleaseCompile|x86.ActiveCfg = Release-Static|Win32 + {A5D9AA24-08ED-48B9-BD65-F0A25E96BFC4}.ReleaseCompile|x86.Build.0 = Release-Static|Win32 + {A5D9AA24-08ED-48B9-BD65-F0A25E96BFC4}.ReleaseLib_win32|Any CPU.ActiveCfg = Release|ARM + {A5D9AA24-08ED-48B9-BD65-F0A25E96BFC4}.ReleaseLib_win32|Any CPU.Build.0 = Release|ARM + {A5D9AA24-08ED-48B9-BD65-F0A25E96BFC4}.ReleaseLib_win32|x64.ActiveCfg = Release|x64 + {A5D9AA24-08ED-48B9-BD65-F0A25E96BFC4}.ReleaseLib_win32|x64.Build.0 = Release|x64 + {A5D9AA24-08ED-48B9-BD65-F0A25E96BFC4}.ReleaseLib_win32|x86.ActiveCfg = Release-Static|Win32 + {A5D9AA24-08ED-48B9-BD65-F0A25E96BFC4}.ReleaseLib_win32|x86.Build.0 = Release-Static|Win32 + {A5D9AA24-08ED-48B9-BD65-F0A25E96BFC4}.ReleaseLib|Any CPU.ActiveCfg = Release|ARM + {A5D9AA24-08ED-48B9-BD65-F0A25E96BFC4}.ReleaseLib|Any CPU.Build.0 = Release|ARM + {A5D9AA24-08ED-48B9-BD65-F0A25E96BFC4}.ReleaseLib|x64.ActiveCfg = Release|x64 + {A5D9AA24-08ED-48B9-BD65-F0A25E96BFC4}.ReleaseLib|x64.Build.0 = Release|x64 + {A5D9AA24-08ED-48B9-BD65-F0A25E96BFC4}.ReleaseLib|x86.ActiveCfg = Release-Static|Win32 + {A5D9AA24-08ED-48B9-BD65-F0A25E96BFC4}.ReleaseLib|x86.Build.0 = Release-Static|Win32 + {7FDE3880-A4AB-49E3-B439-EBEF0A0C7A65}.Beta|Any CPU.ActiveCfg = Release|Win32 + {7FDE3880-A4AB-49E3-B439-EBEF0A0C7A65}.Beta|x64.ActiveCfg = Release|x64 + {7FDE3880-A4AB-49E3-B439-EBEF0A0C7A65}.Beta|x64.Build.0 = Release|x64 + {7FDE3880-A4AB-49E3-B439-EBEF0A0C7A65}.Beta|x86.ActiveCfg = Release|Win32 + {7FDE3880-A4AB-49E3-B439-EBEF0A0C7A65}.Beta|x86.Build.0 = Release|Win32 + {7FDE3880-A4AB-49E3-B439-EBEF0A0C7A65}.Debug|Any CPU.ActiveCfg = Debug|Win32 + {7FDE3880-A4AB-49E3-B439-EBEF0A0C7A65}.Debug|x64.ActiveCfg = Debug|x64 + {7FDE3880-A4AB-49E3-B439-EBEF0A0C7A65}.Debug|x64.Build.0 = Debug|x64 + {7FDE3880-A4AB-49E3-B439-EBEF0A0C7A65}.Debug|x86.ActiveCfg = Debug|Win32 + {7FDE3880-A4AB-49E3-B439-EBEF0A0C7A65}.Debug|x86.Build.0 = Debug|Win32 + {7FDE3880-A4AB-49E3-B439-EBEF0A0C7A65}.Release|Any CPU.ActiveCfg = Release|Win32 + {7FDE3880-A4AB-49E3-B439-EBEF0A0C7A65}.Release|x64.ActiveCfg = Release|x64 + {7FDE3880-A4AB-49E3-B439-EBEF0A0C7A65}.Release|x64.Build.0 = Release|x64 + {7FDE3880-A4AB-49E3-B439-EBEF0A0C7A65}.Release|x86.ActiveCfg = Release|Win32 + {7FDE3880-A4AB-49E3-B439-EBEF0A0C7A65}.Release|x86.Build.0 = Release|Win32 + {7FDE3880-A4AB-49E3-B439-EBEF0A0C7A65}.ReleaseCompile|Any CPU.ActiveCfg = Release|ARM + {7FDE3880-A4AB-49E3-B439-EBEF0A0C7A65}.ReleaseCompile|Any CPU.Build.0 = Release|ARM + {7FDE3880-A4AB-49E3-B439-EBEF0A0C7A65}.ReleaseCompile|x64.ActiveCfg = Release|x64 + {7FDE3880-A4AB-49E3-B439-EBEF0A0C7A65}.ReleaseCompile|x64.Build.0 = Release|x64 + {7FDE3880-A4AB-49E3-B439-EBEF0A0C7A65}.ReleaseCompile|x86.ActiveCfg = Release-Static|Win32 + {7FDE3880-A4AB-49E3-B439-EBEF0A0C7A65}.ReleaseCompile|x86.Build.0 = Release-Static|Win32 + {7FDE3880-A4AB-49E3-B439-EBEF0A0C7A65}.ReleaseLib_win32|Any CPU.ActiveCfg = Release|ARM + {7FDE3880-A4AB-49E3-B439-EBEF0A0C7A65}.ReleaseLib_win32|Any CPU.Build.0 = Release|ARM + {7FDE3880-A4AB-49E3-B439-EBEF0A0C7A65}.ReleaseLib_win32|x64.ActiveCfg = Release|x64 + {7FDE3880-A4AB-49E3-B439-EBEF0A0C7A65}.ReleaseLib_win32|x64.Build.0 = Release|x64 + {7FDE3880-A4AB-49E3-B439-EBEF0A0C7A65}.ReleaseLib_win32|x86.ActiveCfg = Release-Static|Win32 + {7FDE3880-A4AB-49E3-B439-EBEF0A0C7A65}.ReleaseLib_win32|x86.Build.0 = Release-Static|Win32 + {7FDE3880-A4AB-49E3-B439-EBEF0A0C7A65}.ReleaseLib|Any CPU.ActiveCfg = Release|ARM + {7FDE3880-A4AB-49E3-B439-EBEF0A0C7A65}.ReleaseLib|Any CPU.Build.0 = Release|ARM + {7FDE3880-A4AB-49E3-B439-EBEF0A0C7A65}.ReleaseLib|x64.ActiveCfg = Release|x64 + {7FDE3880-A4AB-49E3-B439-EBEF0A0C7A65}.ReleaseLib|x64.Build.0 = Release|x64 + {7FDE3880-A4AB-49E3-B439-EBEF0A0C7A65}.ReleaseLib|x86.ActiveCfg = Release-Static|Win32 + {7FDE3880-A4AB-49E3-B439-EBEF0A0C7A65}.ReleaseLib|x86.Build.0 = Release-Static|Win32 + {855DC8C0-D3E9-4A2E-AE47-116605A7BC9B}.Beta|Any CPU.ActiveCfg = Release|Win32 + {855DC8C0-D3E9-4A2E-AE47-116605A7BC9B}.Beta|x64.ActiveCfg = Release|x64 + {855DC8C0-D3E9-4A2E-AE47-116605A7BC9B}.Beta|x64.Build.0 = Release|x64 + {855DC8C0-D3E9-4A2E-AE47-116605A7BC9B}.Beta|x86.ActiveCfg = Release|Win32 + {855DC8C0-D3E9-4A2E-AE47-116605A7BC9B}.Beta|x86.Build.0 = Release|Win32 + {855DC8C0-D3E9-4A2E-AE47-116605A7BC9B}.Debug|Any CPU.ActiveCfg = Debug|Win32 + {855DC8C0-D3E9-4A2E-AE47-116605A7BC9B}.Debug|x64.ActiveCfg = Debug|x64 + {855DC8C0-D3E9-4A2E-AE47-116605A7BC9B}.Debug|x64.Build.0 = Debug|x64 + {855DC8C0-D3E9-4A2E-AE47-116605A7BC9B}.Debug|x86.ActiveCfg = Debug|Win32 + {855DC8C0-D3E9-4A2E-AE47-116605A7BC9B}.Debug|x86.Build.0 = Debug|Win32 + {855DC8C0-D3E9-4A2E-AE47-116605A7BC9B}.Release|Any CPU.ActiveCfg = Release|Win32 + {855DC8C0-D3E9-4A2E-AE47-116605A7BC9B}.Release|x64.ActiveCfg = Release|x64 + {855DC8C0-D3E9-4A2E-AE47-116605A7BC9B}.Release|x64.Build.0 = Release|x64 + {855DC8C0-D3E9-4A2E-AE47-116605A7BC9B}.Release|x86.ActiveCfg = Release|Win32 + {855DC8C0-D3E9-4A2E-AE47-116605A7BC9B}.Release|x86.Build.0 = Release|Win32 + {855DC8C0-D3E9-4A2E-AE47-116605A7BC9B}.ReleaseCompile|Any CPU.ActiveCfg = Release|ARM + {855DC8C0-D3E9-4A2E-AE47-116605A7BC9B}.ReleaseCompile|Any CPU.Build.0 = Release|ARM + {855DC8C0-D3E9-4A2E-AE47-116605A7BC9B}.ReleaseCompile|x64.ActiveCfg = Release|x64 + {855DC8C0-D3E9-4A2E-AE47-116605A7BC9B}.ReleaseCompile|x64.Build.0 = Release|x64 + {855DC8C0-D3E9-4A2E-AE47-116605A7BC9B}.ReleaseCompile|x86.ActiveCfg = Release-Static|Win32 + {855DC8C0-D3E9-4A2E-AE47-116605A7BC9B}.ReleaseCompile|x86.Build.0 = Release-Static|Win32 + {855DC8C0-D3E9-4A2E-AE47-116605A7BC9B}.ReleaseLib_win32|Any CPU.ActiveCfg = Release|ARM + {855DC8C0-D3E9-4A2E-AE47-116605A7BC9B}.ReleaseLib_win32|Any CPU.Build.0 = Release|ARM + {855DC8C0-D3E9-4A2E-AE47-116605A7BC9B}.ReleaseLib_win32|x64.ActiveCfg = Release|x64 + {855DC8C0-D3E9-4A2E-AE47-116605A7BC9B}.ReleaseLib_win32|x64.Build.0 = Release|x64 + {855DC8C0-D3E9-4A2E-AE47-116605A7BC9B}.ReleaseLib_win32|x86.ActiveCfg = Release-Static|Win32 + {855DC8C0-D3E9-4A2E-AE47-116605A7BC9B}.ReleaseLib_win32|x86.Build.0 = Release-Static|Win32 + {855DC8C0-D3E9-4A2E-AE47-116605A7BC9B}.ReleaseLib|Any CPU.ActiveCfg = Release|ARM + {855DC8C0-D3E9-4A2E-AE47-116605A7BC9B}.ReleaseLib|Any CPU.Build.0 = Release|ARM + {855DC8C0-D3E9-4A2E-AE47-116605A7BC9B}.ReleaseLib|x64.ActiveCfg = Release|x64 + {855DC8C0-D3E9-4A2E-AE47-116605A7BC9B}.ReleaseLib|x64.Build.0 = Release|x64 + {855DC8C0-D3E9-4A2E-AE47-116605A7BC9B}.ReleaseLib|x86.ActiveCfg = Release-Static|Win32 + {855DC8C0-D3E9-4A2E-AE47-116605A7BC9B}.ReleaseLib|x86.Build.0 = Release-Static|Win32 + {FE07F272-AE7F-4549-9E9F-EF9B80CB1693}.Beta|Any CPU.ActiveCfg = Release|Win32 + {FE07F272-AE7F-4549-9E9F-EF9B80CB1693}.Beta|x64.ActiveCfg = Release|x64 + {FE07F272-AE7F-4549-9E9F-EF9B80CB1693}.Beta|x64.Build.0 = Release|x64 + {FE07F272-AE7F-4549-9E9F-EF9B80CB1693}.Beta|x86.ActiveCfg = Release|Win32 + {FE07F272-AE7F-4549-9E9F-EF9B80CB1693}.Beta|x86.Build.0 = Release|Win32 + {FE07F272-AE7F-4549-9E9F-EF9B80CB1693}.Debug|Any CPU.ActiveCfg = Debug|Win32 + {FE07F272-AE7F-4549-9E9F-EF9B80CB1693}.Debug|x64.ActiveCfg = Debug|x64 + {FE07F272-AE7F-4549-9E9F-EF9B80CB1693}.Debug|x64.Build.0 = Debug|x64 + {FE07F272-AE7F-4549-9E9F-EF9B80CB1693}.Debug|x86.ActiveCfg = Debug|Win32 + {FE07F272-AE7F-4549-9E9F-EF9B80CB1693}.Debug|x86.Build.0 = Debug|Win32 + {FE07F272-AE7F-4549-9E9F-EF9B80CB1693}.Release|Any CPU.ActiveCfg = Release|Win32 + {FE07F272-AE7F-4549-9E9F-EF9B80CB1693}.Release|x64.ActiveCfg = Release|x64 + {FE07F272-AE7F-4549-9E9F-EF9B80CB1693}.Release|x64.Build.0 = Release|x64 + {FE07F272-AE7F-4549-9E9F-EF9B80CB1693}.Release|x86.ActiveCfg = Release|Win32 + {FE07F272-AE7F-4549-9E9F-EF9B80CB1693}.Release|x86.Build.0 = Release|Win32 + {FE07F272-AE7F-4549-9E9F-EF9B80CB1693}.ReleaseCompile|Any CPU.ActiveCfg = Release|ARM + {FE07F272-AE7F-4549-9E9F-EF9B80CB1693}.ReleaseCompile|Any CPU.Build.0 = Release|ARM + {FE07F272-AE7F-4549-9E9F-EF9B80CB1693}.ReleaseCompile|x64.ActiveCfg = Release|x64 + {FE07F272-AE7F-4549-9E9F-EF9B80CB1693}.ReleaseCompile|x64.Build.0 = Release|x64 + {FE07F272-AE7F-4549-9E9F-EF9B80CB1693}.ReleaseCompile|x86.ActiveCfg = Release-Static|Win32 + {FE07F272-AE7F-4549-9E9F-EF9B80CB1693}.ReleaseCompile|x86.Build.0 = Release-Static|Win32 + {FE07F272-AE7F-4549-9E9F-EF9B80CB1693}.ReleaseLib_win32|Any CPU.ActiveCfg = Release|ARM + {FE07F272-AE7F-4549-9E9F-EF9B80CB1693}.ReleaseLib_win32|Any CPU.Build.0 = Release|ARM + {FE07F272-AE7F-4549-9E9F-EF9B80CB1693}.ReleaseLib_win32|x64.ActiveCfg = Release|x64 + {FE07F272-AE7F-4549-9E9F-EF9B80CB1693}.ReleaseLib_win32|x64.Build.0 = Release|x64 + {FE07F272-AE7F-4549-9E9F-EF9B80CB1693}.ReleaseLib_win32|x86.ActiveCfg = Release-Static|Win32 + {FE07F272-AE7F-4549-9E9F-EF9B80CB1693}.ReleaseLib_win32|x86.Build.0 = Release-Static|Win32 + {FE07F272-AE7F-4549-9E9F-EF9B80CB1693}.ReleaseLib|Any CPU.ActiveCfg = Release|ARM + {FE07F272-AE7F-4549-9E9F-EF9B80CB1693}.ReleaseLib|Any CPU.Build.0 = Release|ARM + {FE07F272-AE7F-4549-9E9F-EF9B80CB1693}.ReleaseLib|x64.ActiveCfg = Release|x64 + {FE07F272-AE7F-4549-9E9F-EF9B80CB1693}.ReleaseLib|x64.Build.0 = Release|x64 + {FE07F272-AE7F-4549-9E9F-EF9B80CB1693}.ReleaseLib|x86.ActiveCfg = Release-Static|Win32 + {FE07F272-AE7F-4549-9E9F-EF9B80CB1693}.ReleaseLib|x86.Build.0 = Release-Static|Win32 + {DA0E03ED-53A7-4050-8A85-90541C5509F8}.Beta|Any CPU.ActiveCfg = Release|Win32 + {DA0E03ED-53A7-4050-8A85-90541C5509F8}.Beta|x64.ActiveCfg = Release|x64 + {DA0E03ED-53A7-4050-8A85-90541C5509F8}.Beta|x64.Build.0 = Release|x64 + {DA0E03ED-53A7-4050-8A85-90541C5509F8}.Beta|x86.ActiveCfg = Release|Win32 + {DA0E03ED-53A7-4050-8A85-90541C5509F8}.Beta|x86.Build.0 = Release|Win32 + {DA0E03ED-53A7-4050-8A85-90541C5509F8}.Debug|Any CPU.ActiveCfg = Debug|Win32 + {DA0E03ED-53A7-4050-8A85-90541C5509F8}.Debug|x64.ActiveCfg = Debug|x64 + {DA0E03ED-53A7-4050-8A85-90541C5509F8}.Debug|x64.Build.0 = Debug|x64 + {DA0E03ED-53A7-4050-8A85-90541C5509F8}.Debug|x86.ActiveCfg = Debug|Win32 + {DA0E03ED-53A7-4050-8A85-90541C5509F8}.Debug|x86.Build.0 = Debug|Win32 + {DA0E03ED-53A7-4050-8A85-90541C5509F8}.Release|Any CPU.ActiveCfg = Release|Win32 + {DA0E03ED-53A7-4050-8A85-90541C5509F8}.Release|x64.ActiveCfg = Release|x64 + {DA0E03ED-53A7-4050-8A85-90541C5509F8}.Release|x64.Build.0 = Release|x64 + {DA0E03ED-53A7-4050-8A85-90541C5509F8}.Release|x86.ActiveCfg = Release|Win32 + {DA0E03ED-53A7-4050-8A85-90541C5509F8}.Release|x86.Build.0 = Release|Win32 + {DA0E03ED-53A7-4050-8A85-90541C5509F8}.ReleaseCompile|Any CPU.ActiveCfg = Release|ARM + {DA0E03ED-53A7-4050-8A85-90541C5509F8}.ReleaseCompile|Any CPU.Build.0 = Release|ARM + {DA0E03ED-53A7-4050-8A85-90541C5509F8}.ReleaseCompile|x64.ActiveCfg = Release|x64 + {DA0E03ED-53A7-4050-8A85-90541C5509F8}.ReleaseCompile|x64.Build.0 = Release|x64 + {DA0E03ED-53A7-4050-8A85-90541C5509F8}.ReleaseCompile|x86.ActiveCfg = Release-Static|Win32 + {DA0E03ED-53A7-4050-8A85-90541C5509F8}.ReleaseCompile|x86.Build.0 = Release-Static|Win32 + {DA0E03ED-53A7-4050-8A85-90541C5509F8}.ReleaseLib_win32|Any CPU.ActiveCfg = Release|ARM + {DA0E03ED-53A7-4050-8A85-90541C5509F8}.ReleaseLib_win32|Any CPU.Build.0 = Release|ARM + {DA0E03ED-53A7-4050-8A85-90541C5509F8}.ReleaseLib_win32|x64.ActiveCfg = Release|x64 + {DA0E03ED-53A7-4050-8A85-90541C5509F8}.ReleaseLib_win32|x64.Build.0 = Release|x64 + {DA0E03ED-53A7-4050-8A85-90541C5509F8}.ReleaseLib_win32|x86.ActiveCfg = Release-Static|Win32 + {DA0E03ED-53A7-4050-8A85-90541C5509F8}.ReleaseLib_win32|x86.Build.0 = Release-Static|Win32 + {DA0E03ED-53A7-4050-8A85-90541C5509F8}.ReleaseLib|Any CPU.ActiveCfg = Release|ARM + {DA0E03ED-53A7-4050-8A85-90541C5509F8}.ReleaseLib|Any CPU.Build.0 = Release|ARM + {DA0E03ED-53A7-4050-8A85-90541C5509F8}.ReleaseLib|x64.ActiveCfg = Release|x64 + {DA0E03ED-53A7-4050-8A85-90541C5509F8}.ReleaseLib|x64.Build.0 = Release|x64 + {DA0E03ED-53A7-4050-8A85-90541C5509F8}.ReleaseLib|x86.ActiveCfg = Release-Static|Win32 + {DA0E03ED-53A7-4050-8A85-90541C5509F8}.ReleaseLib|x86.Build.0 = Release-Static|Win32 + {2BB84911-C1B4-4747-B93D-36AA82CC5031}.Beta|Any CPU.ActiveCfg = Release|Win32 + {2BB84911-C1B4-4747-B93D-36AA82CC5031}.Beta|x64.ActiveCfg = Release|x64 + {2BB84911-C1B4-4747-B93D-36AA82CC5031}.Beta|x64.Build.0 = Release|x64 + {2BB84911-C1B4-4747-B93D-36AA82CC5031}.Beta|x86.ActiveCfg = Release|Win32 + {2BB84911-C1B4-4747-B93D-36AA82CC5031}.Beta|x86.Build.0 = Release|Win32 + {2BB84911-C1B4-4747-B93D-36AA82CC5031}.Debug|Any CPU.ActiveCfg = Debug|Win32 + {2BB84911-C1B4-4747-B93D-36AA82CC5031}.Debug|x64.ActiveCfg = Debug|x64 + {2BB84911-C1B4-4747-B93D-36AA82CC5031}.Debug|x64.Build.0 = Debug|x64 + {2BB84911-C1B4-4747-B93D-36AA82CC5031}.Debug|x86.ActiveCfg = Debug|Win32 + {2BB84911-C1B4-4747-B93D-36AA82CC5031}.Debug|x86.Build.0 = Debug|Win32 + {2BB84911-C1B4-4747-B93D-36AA82CC5031}.Release|Any CPU.ActiveCfg = Release|Win32 + {2BB84911-C1B4-4747-B93D-36AA82CC5031}.Release|x64.ActiveCfg = Release|x64 + {2BB84911-C1B4-4747-B93D-36AA82CC5031}.Release|x64.Build.0 = Release|x64 + {2BB84911-C1B4-4747-B93D-36AA82CC5031}.Release|x86.ActiveCfg = Release|Win32 + {2BB84911-C1B4-4747-B93D-36AA82CC5031}.Release|x86.Build.0 = Release|Win32 + {2BB84911-C1B4-4747-B93D-36AA82CC5031}.ReleaseCompile|Any CPU.ActiveCfg = Release|ARM + {2BB84911-C1B4-4747-B93D-36AA82CC5031}.ReleaseCompile|Any CPU.Build.0 = Release|ARM + {2BB84911-C1B4-4747-B93D-36AA82CC5031}.ReleaseCompile|x64.ActiveCfg = Release|x64 + {2BB84911-C1B4-4747-B93D-36AA82CC5031}.ReleaseCompile|x64.Build.0 = Release|x64 + {2BB84911-C1B4-4747-B93D-36AA82CC5031}.ReleaseCompile|x86.ActiveCfg = Release-Static|Win32 + {2BB84911-C1B4-4747-B93D-36AA82CC5031}.ReleaseCompile|x86.Build.0 = Release-Static|Win32 + {2BB84911-C1B4-4747-B93D-36AA82CC5031}.ReleaseLib_win32|Any CPU.ActiveCfg = Release|ARM + {2BB84911-C1B4-4747-B93D-36AA82CC5031}.ReleaseLib_win32|Any CPU.Build.0 = Release|ARM + {2BB84911-C1B4-4747-B93D-36AA82CC5031}.ReleaseLib_win32|x64.ActiveCfg = Release|x64 + {2BB84911-C1B4-4747-B93D-36AA82CC5031}.ReleaseLib_win32|x64.Build.0 = Release|x64 + {2BB84911-C1B4-4747-B93D-36AA82CC5031}.ReleaseLib_win32|x86.ActiveCfg = Release-Static|Win32 + {2BB84911-C1B4-4747-B93D-36AA82CC5031}.ReleaseLib_win32|x86.Build.0 = Release-Static|Win32 + {2BB84911-C1B4-4747-B93D-36AA82CC5031}.ReleaseLib|Any CPU.ActiveCfg = Release|ARM + {2BB84911-C1B4-4747-B93D-36AA82CC5031}.ReleaseLib|Any CPU.Build.0 = Release|ARM + {2BB84911-C1B4-4747-B93D-36AA82CC5031}.ReleaseLib|x64.ActiveCfg = Release|x64 + {2BB84911-C1B4-4747-B93D-36AA82CC5031}.ReleaseLib|x64.Build.0 = Release|x64 + {2BB84911-C1B4-4747-B93D-36AA82CC5031}.ReleaseLib|x86.ActiveCfg = Release-Static|Win32 + {2BB84911-C1B4-4747-B93D-36AA82CC5031}.ReleaseLib|x86.Build.0 = Release-Static|Win32 + {B82CDD25-6903-430E-BD38-D8129A2015C1}.Beta|Any CPU.ActiveCfg = Release|Win32 + {B82CDD25-6903-430E-BD38-D8129A2015C1}.Beta|x64.ActiveCfg = Release|x64 + {B82CDD25-6903-430E-BD38-D8129A2015C1}.Beta|x64.Build.0 = Release|x64 + {B82CDD25-6903-430E-BD38-D8129A2015C1}.Beta|x86.ActiveCfg = Release|Win32 + {B82CDD25-6903-430E-BD38-D8129A2015C1}.Beta|x86.Build.0 = Release|Win32 + {B82CDD25-6903-430E-BD38-D8129A2015C1}.Debug|Any CPU.ActiveCfg = Debug|Win32 + {B82CDD25-6903-430E-BD38-D8129A2015C1}.Debug|x64.ActiveCfg = Debug|x64 + {B82CDD25-6903-430E-BD38-D8129A2015C1}.Debug|x64.Build.0 = Debug|x64 + {B82CDD25-6903-430E-BD38-D8129A2015C1}.Debug|x86.ActiveCfg = Debug|Win32 + {B82CDD25-6903-430E-BD38-D8129A2015C1}.Debug|x86.Build.0 = Debug|Win32 + {B82CDD25-6903-430E-BD38-D8129A2015C1}.Release|Any CPU.ActiveCfg = Release|Win32 + {B82CDD25-6903-430E-BD38-D8129A2015C1}.Release|x64.ActiveCfg = Release|x64 + {B82CDD25-6903-430E-BD38-D8129A2015C1}.Release|x64.Build.0 = Release|x64 + {B82CDD25-6903-430E-BD38-D8129A2015C1}.Release|x86.ActiveCfg = Release|Win32 + {B82CDD25-6903-430E-BD38-D8129A2015C1}.Release|x86.Build.0 = Release|Win32 + {B82CDD25-6903-430E-BD38-D8129A2015C1}.ReleaseCompile|Any CPU.ActiveCfg = Release|ARM + {B82CDD25-6903-430E-BD38-D8129A2015C1}.ReleaseCompile|Any CPU.Build.0 = Release|ARM + {B82CDD25-6903-430E-BD38-D8129A2015C1}.ReleaseCompile|x64.ActiveCfg = Release|x64 + {B82CDD25-6903-430E-BD38-D8129A2015C1}.ReleaseCompile|x64.Build.0 = Release|x64 + {B82CDD25-6903-430E-BD38-D8129A2015C1}.ReleaseCompile|x86.ActiveCfg = Release-Static|Win32 + {B82CDD25-6903-430E-BD38-D8129A2015C1}.ReleaseCompile|x86.Build.0 = Release-Static|Win32 + {B82CDD25-6903-430E-BD38-D8129A2015C1}.ReleaseLib_win32|Any CPU.ActiveCfg = Release|ARM + {B82CDD25-6903-430E-BD38-D8129A2015C1}.ReleaseLib_win32|Any CPU.Build.0 = Release|ARM + {B82CDD25-6903-430E-BD38-D8129A2015C1}.ReleaseLib_win32|x64.ActiveCfg = Release|x64 + {B82CDD25-6903-430E-BD38-D8129A2015C1}.ReleaseLib_win32|x64.Build.0 = Release|x64 + {B82CDD25-6903-430E-BD38-D8129A2015C1}.ReleaseLib_win32|x86.ActiveCfg = Release-Static|Win32 + {B82CDD25-6903-430E-BD38-D8129A2015C1}.ReleaseLib_win32|x86.Build.0 = Release-Static|Win32 + {B82CDD25-6903-430E-BD38-D8129A2015C1}.ReleaseLib|Any CPU.ActiveCfg = Release|ARM + {B82CDD25-6903-430E-BD38-D8129A2015C1}.ReleaseLib|Any CPU.Build.0 = Release|ARM + {B82CDD25-6903-430E-BD38-D8129A2015C1}.ReleaseLib|x64.ActiveCfg = Release|x64 + {B82CDD25-6903-430E-BD38-D8129A2015C1}.ReleaseLib|x64.Build.0 = Release|x64 + {B82CDD25-6903-430E-BD38-D8129A2015C1}.ReleaseLib|x86.ActiveCfg = Release-Static|Win32 + {B82CDD25-6903-430E-BD38-D8129A2015C1}.ReleaseLib|x86.Build.0 = Release-Static|Win32 + {9CA0FDFB-2172-41FC-B7F1-5CE915EDCB37}.Beta|Any CPU.ActiveCfg = Release|Win32 + {9CA0FDFB-2172-41FC-B7F1-5CE915EDCB37}.Beta|x64.ActiveCfg = Release|x64 + {9CA0FDFB-2172-41FC-B7F1-5CE915EDCB37}.Beta|x64.Build.0 = Release|x64 + {9CA0FDFB-2172-41FC-B7F1-5CE915EDCB37}.Beta|x86.ActiveCfg = Release|Win32 + {9CA0FDFB-2172-41FC-B7F1-5CE915EDCB37}.Beta|x86.Build.0 = Release|Win32 + {9CA0FDFB-2172-41FC-B7F1-5CE915EDCB37}.Debug|Any CPU.ActiveCfg = Debug|Win32 + {9CA0FDFB-2172-41FC-B7F1-5CE915EDCB37}.Debug|x64.ActiveCfg = Debug|x64 + {9CA0FDFB-2172-41FC-B7F1-5CE915EDCB37}.Debug|x64.Build.0 = Debug|x64 + {9CA0FDFB-2172-41FC-B7F1-5CE915EDCB37}.Debug|x86.ActiveCfg = Debug|Win32 + {9CA0FDFB-2172-41FC-B7F1-5CE915EDCB37}.Debug|x86.Build.0 = Debug|Win32 + {9CA0FDFB-2172-41FC-B7F1-5CE915EDCB37}.Release|Any CPU.ActiveCfg = Release|Win32 + {9CA0FDFB-2172-41FC-B7F1-5CE915EDCB37}.Release|x64.ActiveCfg = Release|x64 + {9CA0FDFB-2172-41FC-B7F1-5CE915EDCB37}.Release|x64.Build.0 = Release|x64 + {9CA0FDFB-2172-41FC-B7F1-5CE915EDCB37}.Release|x86.ActiveCfg = Release|Win32 + {9CA0FDFB-2172-41FC-B7F1-5CE915EDCB37}.Release|x86.Build.0 = Release|Win32 + {9CA0FDFB-2172-41FC-B7F1-5CE915EDCB37}.ReleaseCompile|Any CPU.ActiveCfg = Release|ARM + {9CA0FDFB-2172-41FC-B7F1-5CE915EDCB37}.ReleaseCompile|Any CPU.Build.0 = Release|ARM + {9CA0FDFB-2172-41FC-B7F1-5CE915EDCB37}.ReleaseCompile|x64.ActiveCfg = Release|x64 + {9CA0FDFB-2172-41FC-B7F1-5CE915EDCB37}.ReleaseCompile|x64.Build.0 = Release|x64 + {9CA0FDFB-2172-41FC-B7F1-5CE915EDCB37}.ReleaseCompile|x86.ActiveCfg = Release-Static|Win32 + {9CA0FDFB-2172-41FC-B7F1-5CE915EDCB37}.ReleaseCompile|x86.Build.0 = Release-Static|Win32 + {9CA0FDFB-2172-41FC-B7F1-5CE915EDCB37}.ReleaseLib_win32|Any CPU.ActiveCfg = Release|ARM + {9CA0FDFB-2172-41FC-B7F1-5CE915EDCB37}.ReleaseLib_win32|Any CPU.Build.0 = Release|ARM + {9CA0FDFB-2172-41FC-B7F1-5CE915EDCB37}.ReleaseLib_win32|x64.ActiveCfg = Release|x64 + {9CA0FDFB-2172-41FC-B7F1-5CE915EDCB37}.ReleaseLib_win32|x64.Build.0 = Release|x64 + {9CA0FDFB-2172-41FC-B7F1-5CE915EDCB37}.ReleaseLib_win32|x86.ActiveCfg = Release-Static|Win32 + {9CA0FDFB-2172-41FC-B7F1-5CE915EDCB37}.ReleaseLib_win32|x86.Build.0 = Release-Static|Win32 + {9CA0FDFB-2172-41FC-B7F1-5CE915EDCB37}.ReleaseLib|Any CPU.ActiveCfg = Release|ARM + {9CA0FDFB-2172-41FC-B7F1-5CE915EDCB37}.ReleaseLib|Any CPU.Build.0 = Release|ARM + {9CA0FDFB-2172-41FC-B7F1-5CE915EDCB37}.ReleaseLib|x64.ActiveCfg = Release|x64 + {9CA0FDFB-2172-41FC-B7F1-5CE915EDCB37}.ReleaseLib|x64.Build.0 = Release|x64 + {9CA0FDFB-2172-41FC-B7F1-5CE915EDCB37}.ReleaseLib|x86.ActiveCfg = Release-Static|Win32 + {9CA0FDFB-2172-41FC-B7F1-5CE915EDCB37}.ReleaseLib|x86.Build.0 = Release-Static|Win32 + {4B5945CD-0CB3-49AA-A7FF-7612D93F82C0}.Beta|Any CPU.ActiveCfg = Release|Win32 + {4B5945CD-0CB3-49AA-A7FF-7612D93F82C0}.Beta|x64.ActiveCfg = Release|x64 + {4B5945CD-0CB3-49AA-A7FF-7612D93F82C0}.Beta|x64.Build.0 = Release|x64 + {4B5945CD-0CB3-49AA-A7FF-7612D93F82C0}.Beta|x86.ActiveCfg = Release|Win32 + {4B5945CD-0CB3-49AA-A7FF-7612D93F82C0}.Beta|x86.Build.0 = Release|Win32 + {4B5945CD-0CB3-49AA-A7FF-7612D93F82C0}.Debug|Any CPU.ActiveCfg = Debug|Win32 + {4B5945CD-0CB3-49AA-A7FF-7612D93F82C0}.Debug|x64.ActiveCfg = Debug|x64 + {4B5945CD-0CB3-49AA-A7FF-7612D93F82C0}.Debug|x64.Build.0 = Debug|x64 + {4B5945CD-0CB3-49AA-A7FF-7612D93F82C0}.Debug|x86.ActiveCfg = Debug|Win32 + {4B5945CD-0CB3-49AA-A7FF-7612D93F82C0}.Debug|x86.Build.0 = Debug|Win32 + {4B5945CD-0CB3-49AA-A7FF-7612D93F82C0}.Release|Any CPU.ActiveCfg = Release|Win32 + {4B5945CD-0CB3-49AA-A7FF-7612D93F82C0}.Release|x64.ActiveCfg = Release|x64 + {4B5945CD-0CB3-49AA-A7FF-7612D93F82C0}.Release|x64.Build.0 = Release|x64 + {4B5945CD-0CB3-49AA-A7FF-7612D93F82C0}.Release|x86.ActiveCfg = Release|Win32 + {4B5945CD-0CB3-49AA-A7FF-7612D93F82C0}.Release|x86.Build.0 = Release|Win32 + {4B5945CD-0CB3-49AA-A7FF-7612D93F82C0}.ReleaseCompile|Any CPU.ActiveCfg = Release|ARM + {4B5945CD-0CB3-49AA-A7FF-7612D93F82C0}.ReleaseCompile|Any CPU.Build.0 = Release|ARM + {4B5945CD-0CB3-49AA-A7FF-7612D93F82C0}.ReleaseCompile|x64.ActiveCfg = Release|x64 + {4B5945CD-0CB3-49AA-A7FF-7612D93F82C0}.ReleaseCompile|x64.Build.0 = Release|x64 + {4B5945CD-0CB3-49AA-A7FF-7612D93F82C0}.ReleaseCompile|x86.ActiveCfg = Release-Static|Win32 + {4B5945CD-0CB3-49AA-A7FF-7612D93F82C0}.ReleaseCompile|x86.Build.0 = Release-Static|Win32 + {4B5945CD-0CB3-49AA-A7FF-7612D93F82C0}.ReleaseLib_win32|Any CPU.ActiveCfg = Release|ARM + {4B5945CD-0CB3-49AA-A7FF-7612D93F82C0}.ReleaseLib_win32|Any CPU.Build.0 = Release|ARM + {4B5945CD-0CB3-49AA-A7FF-7612D93F82C0}.ReleaseLib_win32|x64.ActiveCfg = Release|x64 + {4B5945CD-0CB3-49AA-A7FF-7612D93F82C0}.ReleaseLib_win32|x64.Build.0 = Release|x64 + {4B5945CD-0CB3-49AA-A7FF-7612D93F82C0}.ReleaseLib_win32|x86.ActiveCfg = Release-Static|Win32 + {4B5945CD-0CB3-49AA-A7FF-7612D93F82C0}.ReleaseLib_win32|x86.Build.0 = Release-Static|Win32 + {4B5945CD-0CB3-49AA-A7FF-7612D93F82C0}.ReleaseLib|Any CPU.ActiveCfg = Release|ARM + {4B5945CD-0CB3-49AA-A7FF-7612D93F82C0}.ReleaseLib|Any CPU.Build.0 = Release|ARM + {4B5945CD-0CB3-49AA-A7FF-7612D93F82C0}.ReleaseLib|x64.ActiveCfg = Release|x64 + {4B5945CD-0CB3-49AA-A7FF-7612D93F82C0}.ReleaseLib|x64.Build.0 = Release|x64 + {4B5945CD-0CB3-49AA-A7FF-7612D93F82C0}.ReleaseLib|x86.ActiveCfg = Release-Static|Win32 + {4B5945CD-0CB3-49AA-A7FF-7612D93F82C0}.ReleaseLib|x86.Build.0 = Release-Static|Win32 + {B8719FD5-E8A6-4A36-943C-891D07F5DD21}.Beta|Any CPU.ActiveCfg = Release|Win32 + {B8719FD5-E8A6-4A36-943C-891D07F5DD21}.Beta|x64.ActiveCfg = Release|x64 + {B8719FD5-E8A6-4A36-943C-891D07F5DD21}.Beta|x64.Build.0 = Release|x64 + {B8719FD5-E8A6-4A36-943C-891D07F5DD21}.Beta|x86.ActiveCfg = Release|Win32 + {B8719FD5-E8A6-4A36-943C-891D07F5DD21}.Beta|x86.Build.0 = Release|Win32 + {B8719FD5-E8A6-4A36-943C-891D07F5DD21}.Debug|Any CPU.ActiveCfg = Debug|Win32 + {B8719FD5-E8A6-4A36-943C-891D07F5DD21}.Debug|x64.ActiveCfg = Debug|x64 + {B8719FD5-E8A6-4A36-943C-891D07F5DD21}.Debug|x64.Build.0 = Debug|x64 + {B8719FD5-E8A6-4A36-943C-891D07F5DD21}.Debug|x86.ActiveCfg = Debug|Win32 + {B8719FD5-E8A6-4A36-943C-891D07F5DD21}.Debug|x86.Build.0 = Debug|Win32 + {B8719FD5-E8A6-4A36-943C-891D07F5DD21}.Release|Any CPU.ActiveCfg = Release|Win32 + {B8719FD5-E8A6-4A36-943C-891D07F5DD21}.Release|x64.ActiveCfg = Release|x64 + {B8719FD5-E8A6-4A36-943C-891D07F5DD21}.Release|x64.Build.0 = Release|x64 + {B8719FD5-E8A6-4A36-943C-891D07F5DD21}.Release|x86.ActiveCfg = Release|Win32 + {B8719FD5-E8A6-4A36-943C-891D07F5DD21}.Release|x86.Build.0 = Release|Win32 + {B8719FD5-E8A6-4A36-943C-891D07F5DD21}.ReleaseCompile|Any CPU.ActiveCfg = Release|ARM + {B8719FD5-E8A6-4A36-943C-891D07F5DD21}.ReleaseCompile|Any CPU.Build.0 = Release|ARM + {B8719FD5-E8A6-4A36-943C-891D07F5DD21}.ReleaseCompile|x64.ActiveCfg = Release|x64 + {B8719FD5-E8A6-4A36-943C-891D07F5DD21}.ReleaseCompile|x64.Build.0 = Release|x64 + {B8719FD5-E8A6-4A36-943C-891D07F5DD21}.ReleaseCompile|x86.ActiveCfg = Release-Static|Win32 + {B8719FD5-E8A6-4A36-943C-891D07F5DD21}.ReleaseCompile|x86.Build.0 = Release-Static|Win32 + {B8719FD5-E8A6-4A36-943C-891D07F5DD21}.ReleaseLib_win32|Any CPU.ActiveCfg = Release|ARM + {B8719FD5-E8A6-4A36-943C-891D07F5DD21}.ReleaseLib_win32|Any CPU.Build.0 = Release|ARM + {B8719FD5-E8A6-4A36-943C-891D07F5DD21}.ReleaseLib_win32|x64.ActiveCfg = Release|x64 + {B8719FD5-E8A6-4A36-943C-891D07F5DD21}.ReleaseLib_win32|x64.Build.0 = Release|x64 + {B8719FD5-E8A6-4A36-943C-891D07F5DD21}.ReleaseLib_win32|x86.ActiveCfg = Release-Static|Win32 + {B8719FD5-E8A6-4A36-943C-891D07F5DD21}.ReleaseLib_win32|x86.Build.0 = Release-Static|Win32 + {B8719FD5-E8A6-4A36-943C-891D07F5DD21}.ReleaseLib|Any CPU.ActiveCfg = Release|ARM + {B8719FD5-E8A6-4A36-943C-891D07F5DD21}.ReleaseLib|Any CPU.Build.0 = Release|ARM + {B8719FD5-E8A6-4A36-943C-891D07F5DD21}.ReleaseLib|x64.ActiveCfg = Release|x64 + {B8719FD5-E8A6-4A36-943C-891D07F5DD21}.ReleaseLib|x64.Build.0 = Release|x64 + {B8719FD5-E8A6-4A36-943C-891D07F5DD21}.ReleaseLib|x86.ActiveCfg = Release-Static|Win32 + {B8719FD5-E8A6-4A36-943C-891D07F5DD21}.ReleaseLib|x86.Build.0 = Release-Static|Win32 + {711397CE-E5D5-467D-9457-8716C047E50C}.Beta|Any CPU.ActiveCfg = Release|Win32 + {711397CE-E5D5-467D-9457-8716C047E50C}.Beta|x64.ActiveCfg = Release|x64 + {711397CE-E5D5-467D-9457-8716C047E50C}.Beta|x64.Build.0 = Release|x64 + {711397CE-E5D5-467D-9457-8716C047E50C}.Beta|x86.ActiveCfg = Release|Win32 + {711397CE-E5D5-467D-9457-8716C047E50C}.Beta|x86.Build.0 = Release|Win32 + {711397CE-E5D5-467D-9457-8716C047E50C}.Debug|Any CPU.ActiveCfg = Debug|Win32 + {711397CE-E5D5-467D-9457-8716C047E50C}.Debug|x64.ActiveCfg = Debug|x64 + {711397CE-E5D5-467D-9457-8716C047E50C}.Debug|x64.Build.0 = Debug|x64 + {711397CE-E5D5-467D-9457-8716C047E50C}.Debug|x86.ActiveCfg = Debug|Win32 + {711397CE-E5D5-467D-9457-8716C047E50C}.Debug|x86.Build.0 = Debug|Win32 + {711397CE-E5D5-467D-9457-8716C047E50C}.Release|Any CPU.ActiveCfg = Release|Win32 + {711397CE-E5D5-467D-9457-8716C047E50C}.Release|x64.ActiveCfg = Release|x64 + {711397CE-E5D5-467D-9457-8716C047E50C}.Release|x64.Build.0 = Release|x64 + {711397CE-E5D5-467D-9457-8716C047E50C}.Release|x86.ActiveCfg = Release|Win32 + {711397CE-E5D5-467D-9457-8716C047E50C}.Release|x86.Build.0 = Release|Win32 + {711397CE-E5D5-467D-9457-8716C047E50C}.ReleaseCompile|Any CPU.ActiveCfg = Release|x64 + {711397CE-E5D5-467D-9457-8716C047E50C}.ReleaseCompile|Any CPU.Build.0 = Release|x64 + {711397CE-E5D5-467D-9457-8716C047E50C}.ReleaseCompile|x64.ActiveCfg = Release|x64 + {711397CE-E5D5-467D-9457-8716C047E50C}.ReleaseCompile|x64.Build.0 = Release|x64 + {711397CE-E5D5-467D-9457-8716C047E50C}.ReleaseCompile|x86.ActiveCfg = Release|Win32 + {711397CE-E5D5-467D-9457-8716C047E50C}.ReleaseCompile|x86.Build.0 = Release|Win32 + {711397CE-E5D5-467D-9457-8716C047E50C}.ReleaseLib_win32|Any CPU.ActiveCfg = Release|x64 + {711397CE-E5D5-467D-9457-8716C047E50C}.ReleaseLib_win32|Any CPU.Build.0 = Release|x64 + {711397CE-E5D5-467D-9457-8716C047E50C}.ReleaseLib_win32|x64.ActiveCfg = Release|x64 + {711397CE-E5D5-467D-9457-8716C047E50C}.ReleaseLib_win32|x64.Build.0 = Release|x64 + {711397CE-E5D5-467D-9457-8716C047E50C}.ReleaseLib_win32|x86.ActiveCfg = Release|Win32 + {711397CE-E5D5-467D-9457-8716C047E50C}.ReleaseLib_win32|x86.Build.0 = Release|Win32 + {711397CE-E5D5-467D-9457-8716C047E50C}.ReleaseLib|Any CPU.ActiveCfg = Release|x64 + {711397CE-E5D5-467D-9457-8716C047E50C}.ReleaseLib|Any CPU.Build.0 = Release|x64 + {711397CE-E5D5-467D-9457-8716C047E50C}.ReleaseLib|x64.ActiveCfg = Release|x64 + {711397CE-E5D5-467D-9457-8716C047E50C}.ReleaseLib|x64.Build.0 = Release|x64 + {711397CE-E5D5-467D-9457-8716C047E50C}.ReleaseLib|x86.ActiveCfg = Release|Win32 + {711397CE-E5D5-467D-9457-8716C047E50C}.ReleaseLib|x86.Build.0 = Release|Win32 + {A1BDC12C-5DF6-3E77-9793-AB9AB5C82027}.Beta|Any CPU.ActiveCfg = Release|x64 + {A1BDC12C-5DF6-3E77-9793-AB9AB5C82027}.Beta|Any CPU.Build.0 = Release|x64 + {A1BDC12C-5DF6-3E77-9793-AB9AB5C82027}.Beta|x64.ActiveCfg = Release|x64 + {A1BDC12C-5DF6-3E77-9793-AB9AB5C82027}.Beta|x64.Build.0 = Release|x64 + {A1BDC12C-5DF6-3E77-9793-AB9AB5C82027}.Beta|x86.ActiveCfg = Release|x64 + {A1BDC12C-5DF6-3E77-9793-AB9AB5C82027}.Beta|x86.Build.0 = Release|x64 + {A1BDC12C-5DF6-3E77-9793-AB9AB5C82027}.Debug|Any CPU.ActiveCfg = Debug|x64 + {A1BDC12C-5DF6-3E77-9793-AB9AB5C82027}.Debug|x64.ActiveCfg = Debug|x64 + {A1BDC12C-5DF6-3E77-9793-AB9AB5C82027}.Debug|x64.Build.0 = Debug|x64 + {A1BDC12C-5DF6-3E77-9793-AB9AB5C82027}.Debug|x86.ActiveCfg = Debug|x64 + {A1BDC12C-5DF6-3E77-9793-AB9AB5C82027}.Release|Any CPU.ActiveCfg = Release|x64 + {A1BDC12C-5DF6-3E77-9793-AB9AB5C82027}.Release|x64.ActiveCfg = Release|x64 + {A1BDC12C-5DF6-3E77-9793-AB9AB5C82027}.Release|x64.Build.0 = Release|x64 + {A1BDC12C-5DF6-3E77-9793-AB9AB5C82027}.Release|x86.ActiveCfg = Release|x64 + {A1BDC12C-5DF6-3E77-9793-AB9AB5C82027}.ReleaseCompile|Any CPU.ActiveCfg = Release|x64 + {A1BDC12C-5DF6-3E77-9793-AB9AB5C82027}.ReleaseCompile|Any CPU.Build.0 = Release|x64 + {A1BDC12C-5DF6-3E77-9793-AB9AB5C82027}.ReleaseCompile|x64.ActiveCfg = Release|x64 + {A1BDC12C-5DF6-3E77-9793-AB9AB5C82027}.ReleaseCompile|x64.Build.0 = Release|x64 + {A1BDC12C-5DF6-3E77-9793-AB9AB5C82027}.ReleaseCompile|x86.ActiveCfg = Release|x64 + {A1BDC12C-5DF6-3E77-9793-AB9AB5C82027}.ReleaseCompile|x86.Build.0 = Release|x64 + {A1BDC12C-5DF6-3E77-9793-AB9AB5C82027}.ReleaseLib_win32|Any CPU.ActiveCfg = Release|x64 + {A1BDC12C-5DF6-3E77-9793-AB9AB5C82027}.ReleaseLib_win32|Any CPU.Build.0 = Release|x64 + {A1BDC12C-5DF6-3E77-9793-AB9AB5C82027}.ReleaseLib_win32|x64.ActiveCfg = Release|x64 + {A1BDC12C-5DF6-3E77-9793-AB9AB5C82027}.ReleaseLib_win32|x64.Build.0 = Release|x64 + {A1BDC12C-5DF6-3E77-9793-AB9AB5C82027}.ReleaseLib_win32|x86.ActiveCfg = Release|x64 + {A1BDC12C-5DF6-3E77-9793-AB9AB5C82027}.ReleaseLib_win32|x86.Build.0 = Release|x64 + {A1BDC12C-5DF6-3E77-9793-AB9AB5C82027}.ReleaseLib|Any CPU.ActiveCfg = Release|x64 + {A1BDC12C-5DF6-3E77-9793-AB9AB5C82027}.ReleaseLib|Any CPU.Build.0 = Release|x64 + {A1BDC12C-5DF6-3E77-9793-AB9AB5C82027}.ReleaseLib|x64.ActiveCfg = Release|x64 + {A1BDC12C-5DF6-3E77-9793-AB9AB5C82027}.ReleaseLib|x64.Build.0 = Release|x64 + {A1BDC12C-5DF6-3E77-9793-AB9AB5C82027}.ReleaseLib|x86.ActiveCfg = Release|x64 + {A1BDC12C-5DF6-3E77-9793-AB9AB5C82027}.ReleaseLib|x86.Build.0 = Release|x64 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection + GlobalSection(NestedProjects) = preSolution + {1CA4822C-F599-3879-A78F-332D823E4871} = {B6752729-7398-46FA-9CF0-DC854C6AB8CA} + {774F1C61-6659-36E6-9519-17A753890576} = {31F92F98-3580-445D-A3DA-D081B427A562} + {2CFF20AA-9341-3564-A044-C38E70D5372A} = {31F92F98-3580-445D-A3DA-D081B427A562} + {DBBFBC55-1C20-4D21-AE3B-6E8B14C4FE48} = {1ECB5BD6-B3A0-4135-BA3F-48FC367B61C9} + {A5D9AA24-08ED-48B9-BD65-F0A25E96BFC4} = {14A77BA7-0E23-4D8F-A74F-5D5D5583035D} + {14A77BA7-0E23-4D8F-A74F-5D5D5583035D} = {B4FD804C-ABD9-4F54-858B-911F0119580C} + {7FDE3880-A4AB-49E3-B439-EBEF0A0C7A65} = {14A77BA7-0E23-4D8F-A74F-5D5D5583035D} + {855DC8C0-D3E9-4A2E-AE47-116605A7BC9B} = {14A77BA7-0E23-4D8F-A74F-5D5D5583035D} + {FE07F272-AE7F-4549-9E9F-EF9B80CB1693} = {14A77BA7-0E23-4D8F-A74F-5D5D5583035D} + {DA0E03ED-53A7-4050-8A85-90541C5509F8} = {14A77BA7-0E23-4D8F-A74F-5D5D5583035D} + {2BB84911-C1B4-4747-B93D-36AA82CC5031} = {14A77BA7-0E23-4D8F-A74F-5D5D5583035D} + {B82CDD25-6903-430E-BD38-D8129A2015C1} = {14A77BA7-0E23-4D8F-A74F-5D5D5583035D} + {9CA0FDFB-2172-41FC-B7F1-5CE915EDCB37} = {14A77BA7-0E23-4D8F-A74F-5D5D5583035D} + {4B5945CD-0CB3-49AA-A7FF-7612D93F82C0} = {14A77BA7-0E23-4D8F-A74F-5D5D5583035D} + {B8719FD5-E8A6-4A36-943C-891D07F5DD21} = {14A77BA7-0E23-4D8F-A74F-5D5D5583035D} + {B4FD804C-ABD9-4F54-858B-911F0119580C} = {B6752729-7398-46FA-9CF0-DC854C6AB8CA} + {711397CE-E5D5-467D-9457-8716C047E50C} = {B4FD804C-ABD9-4F54-858B-911F0119580C} + {A1BDC12C-5DF6-3E77-9793-AB9AB5C82027} = {1ECB5BD6-B3A0-4135-BA3F-48FC367B61C9} + EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + SolutionGuid = {5C2901E8-26FE-444A-A80E-02AF8147CD34} + EndGlobalSection +EndGlobal diff --git a/make-client.py b/make-client.py new file mode 100644 index 00000000..a496e2ee --- /dev/null +++ b/make-client.py @@ -0,0 +1,249 @@ +import tempfile +import re +import sys +import os +import subprocess +import platform +import argparse +import multiprocessing +import fileinput +import re + +# vs help +win_sdk_default = '10.0.16299.0' +win_toolset_default = 'v141' + +vs_where_path = os.path.join( + os.environ['ProgramFiles(x86)'], 'Microsoft Visual Studio', 'Installer', 'vswhere.exe' +) + +host_is_64bit = (False, True)[platform.machine().endswith('64')] + +def execute_cmd(cmd, with_shell=False, env_vars={}): + if(bool(env_vars)): + p = subprocess.Popen(cmd, shell=with_shell, + stdout=sys.stdout, + env=env_vars) + else: + p = subprocess.Popen(cmd, shell=with_shell) + _, _ = p.communicate() + return p.returncode + +def getLatestVSVersion(): + args = [ + '-latest', + '-products *', + '-requires Microsoft.VisualStudio.Component.VC.Tools.x86.x64', + '-property installationVersion' + ] + cmd = [vs_where_path] + args + output = subprocess.check_output(' '.join(cmd)).decode('utf-8') + if output: + return output.splitlines()[0].split('.')[0] + else: + return + + +def findVSLatestDir(): + args = [ + '-latest', + '-products *', + '-requires Microsoft.VisualStudio.Component.VC.Tools.x86.x64', + '-property installationPath' + ] + cmd = [vs_where_path] + args + output = subprocess.check_output(' '.join(cmd)).decode('utf-8', errors='ignore') + if output: + return output.splitlines()[0] + else: + return + + +def findMSBuild(): + filename = 'MSBuild.exe' + for root, _, files in os.walk(findVSLatestDir() + r'\\MSBuild'): + if filename in files: + return os.path.join(root, filename) + + +def getVSEnv(arch='x64', platform='', version=''): + env_cmd = 'set path=%path:"=% && ' + \ + getVSEnvCmd(arch, platform, version) + ' && set' + p = subprocess.Popen(env_cmd, + shell=True, + stdout=subprocess.PIPE) + stdout, _ = p.communicate() + out = stdout.decode('utf-8', errors='ignore').split("\r\n")[5:-1] + return dict(s.split('=', 1) for s in out) + +def getVSEnvCmd(arch='x64', platform='', version=''): + vcEnvInit = [findVSLatestDir() + r'\VC\Auxiliary\Build\"vcvarsall.bat'] + if platform != '': + args = [arch, platform, version] + else: + args = [arch, version] + if args: + vcEnvInit.extend(args) + vcEnvInit = 'call \"' + ' '.join(vcEnvInit) + return vcEnvInit + +def build_project(msbuild, msbuild_args, proj, env_vars): + args = [] + args.extend(msbuild_args) + args.append(proj) + cmd = [msbuild] + cmd.extend(args) + if (execute_cmd(cmd, True, env_vars)): + print("Build failed when building ", proj) + sys.exit(1) + +def replace_vs_prop(filename, prop, val): + p = re.compile(r'(?s)<' + prop + r'\s?.*?>(.*?)<\/' + prop + r'>') + val = r'<' + prop + r'>' + val + r'' + with fileinput.FileInput(filename, inplace=True) as file: + for line in file: + print(re.sub(p, val, line), end='') + +def deps(arch, toolset, qtver): + print('Deps Qt Client Release|' + arch) + + # Fetch QRencode + print('Generate QRencode') + apply_cmd = "git apply --reject --ignore-whitespace --whitespace=fix" + qrencode_path = 'qrencode-win32' + if (os.path.isdir(qrencode_path)): + os.system('rmdir qrencode-win32 /s /q') + if (execute_cmd("git clone https://github.com/BlueDragon747/qrencode-win32.git", True)): + print("Git clone failed when cloning from https://github.com/BlueDragon747/qrencode-win32.git") + sys.exit(1) + if(execute_cmd("cd qrencode-win32 && git checkout d6495a2aa74d058d54ae0f1b9e9e545698de66ce && " + apply_cmd + ' ..\\qrencode-win32.patch', True)): + print("Qrencode-win32 set up error") + sys.exit(1) + + print('Building qrcodelib') + build(arch, '', '', 'Release-Lib', '\\qrencode-win32\\qrencode-win32\\vc8\\qrcodelib\\qrcodelib.vcxproj', qtver, False) + +def build(arch, toolset, sdk_version, config_str, project_path_under_current_path, qtver, force_option=True): + configuration_type = 'StaticLibrary' + + qtFolderDir = "msvc2017_64" + qtverSplit = qtver.split('.') + + if((int(qtverSplit[0]) >= 6) or((int(qtverSplit[0]) == 5) and (int(qtverSplit[1]) >= 15))): + qtFolderDir = "msvc2019_64" + + if (config_str == 'Release'): + print('Generating project using qmake ' + config_str + '|' + arch) + if(execute_cmd("C:\\Qt\\" + qtver + "\\" + qtFolderDir + "\\bin\\qmake.exe " + "-tp vc jami-qt.pro -o jami-qt.vcxproj")): + print("Qmake vcxproj file generate error") + sys.exit(1) + configuration_type = 'Application' + elif (config_str == 'Beta'): + print('Generating project using qmake ' + config_str + '|' + arch) + if(execute_cmd("C:\\Qt\\" + qtver + "\\" + qtFolderDir + "\\bin\\qmake.exe " + "-tp vc jami-qt.pro -o jami-qt.vcxproj CONFIG+=Beta")): + print("Beat: Qmake vcxproj file generate error") + sys.exit(1) + config_str = 'Release' + configuration_type = 'Application' + elif (config_str == 'ReleaseCompile'): + print('Generating project using qmake ' + config_str + '|' + arch) + if(execute_cmd("C:\\Qt\\" + qtver + "\\" + qtFolderDir + "\\bin\\qmake.exe " + "-tp vc jami-qt.pro -o jami-qt.vcxproj CONFIG+=ReleaseCompile")): + print("ReleaseCompile: Qmake vcxproj file generate error") + sys.exit(1) + config_str = 'Release' + + # Note: If project is configured to Beta or ReleaseCompile, the configuration name is still release, + # but will be outputted into x64/Beta folder (for Beta Only) + + print('Building projects in ' + config_str + '|' + arch) + vs_env_vars = {} + vs_env_vars.update(getVSEnv()) + this_dir = os.path.dirname(os.path.realpath(__file__)) + qt_client_proj_path = this_dir + project_path_under_current_path + + msbuild = findMSBuild() + if not os.path.isfile(msbuild): + raise IOError('msbuild.exe not found. path=' + msbuild) + msbuild_args = [ + '/nologo', + '/verbosity:minimal', + '/maxcpucount:' + str(multiprocessing.cpu_count()), + '/p:Platform=' + arch, + '/p:Configuration=' + config_str, + '/p:ConfigurationType=' + configuration_type, + '/p:useenv=true'] + if (toolset != ''): + msbuild_args.append('/p:PlatformToolset=' + toolset) + if (force_option): + # force toolset + replace_vs_prop(qt_client_proj_path, + 'PlatformToolset', + toolset) + # force unicode + replace_vs_prop(qt_client_proj_path, + 'CharacterSet', + 'Unicode') + # force sdk_version + replace_vs_prop(qt_client_proj_path, + 'WindowsTargetPlatformVersion', + sdk_version) + + build_project(msbuild, msbuild_args, qt_client_proj_path, vs_env_vars) + +def parse_args(): + ap = argparse.ArgumentParser(description="Windows Jami-lrc build tool") + ap.add_argument( + '-b', '--build', action='store_true', + help='Build Qt Client') + ap.add_argument( + '-a', '--arch', default='x64', + help='Sets the build architecture') + ap.add_argument( + '-d', '--deps', action='store_true', + help='Build Deps for Qt Client') + ap.add_argument( + '-bt', '--beta', action='store_true', + help='Build Qt Client in Beta Config') + ap.add_argument( + '-c', '--releasecompile', action='store_true', + help='Build Qt Client in ReleaseCompile Config') + ap.add_argument( + '-s', '--sdk', default=win_sdk_default, type=str, + help='Use specified windows sdk version') + ap.add_argument( + '-t', '--toolset', default=win_toolset_default, type=str, + help='Use specified platform toolset version') + ap.add_argument( + '-q', '--qtver', default='5.9.4', + help='Sets the version of Qmake') + + parsed_args = ap.parse_args() + + return parsed_args + + +def main(): + if not host_is_64bit: + print('These scripts will only run on a 64-bit Windows system for now!') + sys.exit(1) + + if int(getLatestVSVersion()) < 15: + print('These scripts require at least Visual Studio v15 2017!') + sys.exit(1) + + parsed_args = parse_args() + + if parsed_args.deps: + deps(parsed_args.arch, parsed_args.toolset, parsed_args.qtver) + + if parsed_args.build: + build(parsed_args.arch, parsed_args.toolset, parsed_args.sdk, 'Release', '\\jami-qt.vcxproj', parsed_args.qtver) + + if parsed_args.beta: + build(parsed_args.arch, parsed_args.toolset, parsed_args.sdk, 'Beta', '\\jami-qt.vcxproj', parsed_args.qtver) + + if parsed_args.releasecompile: + build(parsed_args.arch, parsed_args.toolset, parsed_args.sdk, 'ReleaseCompile', '\\jami-qt.vcxproj', parsed_args.qtver) + +if __name__ == '__main__': + main() diff --git a/projectcredits.html b/projectcredits.html new file mode 100644 index 00000000..e5f7b6bb --- /dev/null +++ b/projectcredits.html @@ -0,0 +1,40 @@ +

Alexandre Lision

+

Alexandr Sergheev

+

Adrien Béraud

+

Alexandre Viau

+

Aline Bonnet

+

Andreas Traczyk

+

Anthony Léonard

+

Cyrille Béraud

+

Dorina Mosku

+

Eden Abitbol

+

Édric Milaret

+

Éloi Bail

+

Emmanuel Lepage-Vallée

+

Frédéric Guimont

+

Guillaume Roguez

+

Hadrien De Sousa

+

Julien Grossholtz

+

Kateryna Kostiuk

+

Loïc Siret

+

Mingrui Zhang

+

Mohamed Amine Younes Bouacida

+

Nicolas Jäger

+

Nicolas Reynaud

+

Olivier Gregoire

+

Olivier Soldano

+

Patrick Keroulas

+

Philippe Gorley

+

Pierre Lespagnol

+

Rayan Osseiran

+

Romain Bertozzi

+

Sébastien Blin

+

Silbino Gonçalves Matado

+

Simon Désaulniers

+

Stepan Salenikovich

+

Simon Zeni

+

Thibault Wittemberg

+

Vsevolod Ivanov

+

Yang Wang

+

Marianne Forget

+


\ No newline at end of file diff --git a/qml.qrc b/qml.qrc new file mode 100644 index 00000000..d939b564 --- /dev/null +++ b/qml.qrc @@ -0,0 +1,96 @@ + + + src/settingsview/SettingsView.qml + src/settingsview/components/IconButton.qml + src/settingsview/components/LeftPanelView.qml + src/settingsview/components/AvSettingPage.qml + src/settingsview/components/GeneralSettingsPage.qml + src/settingsview/components/PluginSettingsPage.qml + src/settingsview/components/PluginListSettingsView.qml + src/settingsview/components/PluginListPreferencesView.qml + src/settingsview/components/CurrentAccountSettingsScrollPage.qml + src/settingsview/components/CurrentSIPAccountSettingScrollPage.qml + src/settingsview/components/ToggleSwitch.qml + src/settingsview/components/AdvancedSettingsView.qml + src/settingsview/components/AdvancedSIPSettingsView.qml + src/settingsview/components/LevelMeter.qml + src/settingsview/components/SettingParaCombobox.qml + src/settingsview/components/DeviceItemDelegate.qml + src/settingsview/components/PluginItemDelegate.qml + src/settingsview/components/PreferenceItemDelegate.qml + src/settingsview/components/BannedItemDelegate.qml + src/settingsview/components/VideoCodecDelegate.qml + src/settingsview/components/AudioCodecDelegate.qml + src/settingsview/components/NameRegistrationDialog.qml + src/settingsview/components/LinkDeviceDialog.qml + src/settingsview/components/RevokeDevicePasswordDialog.qml + src/commoncomponents/HoverableButtonTextItem.qml + src/commoncomponents/HoverableRadiusButton.qml + src/commoncomponents/PasswordDialog.qml + src/commoncomponents/InfoLineEdit.qml + src/commoncomponents/PhotoboothView.qml + src/commoncomponents/LookupStatusLabel.qml + src/commoncomponents/ListViewJami.qml + src/commoncomponents/DeleteAccountDialog.qml + src/commoncomponents/MessageBox.qml + src/wizardview/WizardView.qml + src/wizardview/components/WelcomePageLayout.qml + src/wizardview/components/CreateAccountPage.qml + src/wizardview/components/CreateSIPAccountPage.qml + src/wizardview/components/ImportFromBackupPage.qml + src/wizardview/components/BackupKeyPage.qml + src/wizardview/components/ImportFromDevicePage.qml + src/wizardview/components/ConnectToAccountManagerPage.qml + src/wizardview/components/SpinnerPage.qml + src/wizardview/components/CollapsiblePasswordWidget.qml + src/MainApplicationWindow.qml + src/mainview/MainView.qml + src/commoncomponents/CustomBorder.qml + src/constant/JamiTheme.qml + src/mainview/components/AboutPopUp.qml + src/mainview/components/SidePanel.qml + src/mainview/components/WelcomePage.qml + src/mainview/components/MessageWebView.qml + src/mainview/components/MessageWebViewHeader.qml + src/commoncomponents/HoverableButton.qml + src/mainview/components/AccountComboBox.qml + src/mainview/components/ConversationSmartListView.qml + src/commoncomponents/JamiFileDialog.qml + src/mainview/components/CallStackView.qml + src/mainview/components/IncomingCallPage.qml + src/mainview/components/OutgoingCallPage.qml + src/mainview/components/AudioCallPage.qml + src/mainview/components/CallOverlay.qml + src/commoncomponents/TintedButton.qml + src/mainview/components/CallOverlayButtonGroup.qml + src/mainview/js/incomingcallpagecreation.js + src/mainview/components/ContactSearchBar.qml + src/mainview/components/VideoCallPage.qml + src/mainview/components/ChangeLogScrollView.qml + src/mainview/components/ProjectCreditsScrollView.qml + src/mainview/components/AccountComboBoxPopup.qml + src/mainview/components/ConversationSmartListViewItemDelegate.qml + src/mainview/components/ConversationSmartListUserImage.qml + src/mainview/components/SidePanelTabBar.qml + src/mainview/components/WelcomePageQrDialog.qml + src/commoncomponents/GeneralMenuItem.qml + src/mainview/components/ConversationSmartListContextMenu.qml + src/commoncomponents/GeneralMenuSeparator.qml + src/mainview/components/UserProfile.qml + src/mainview/components/VideoCallPageContextMenu.qml + src/mainview/js/videodevicecontextmenuitemcreation.js + src/mainview/components/VideoCallPageContextMenuDeviceItem.qml + src/mainview/components/SelectScreen.qml + src/mainview/js/selectscreenwindowcreation.js + src/mainview/components/ScreenRubberBand.qml + src/mainview/js/screenrubberbandcreation.js + src/mainview/js/videocallfullscreenwindowcontainercreation.js + src/mainview/components/VideoCallFullScreenWindowContainer.qml + src/mainview/components/ContactPicker.qml + src/mainview/js/contactpickercreation.js + src/mainview/components/ContactPickerItemDelegate.qml + src/wizardview/components/HoverableGradientButton.qml + src/commoncomponents/AccountMigrationDialog.qml + src/mainview/components/RecordBox.qml + + diff --git a/qrencode-win32.patch b/qrencode-win32.patch new file mode 100644 index 00000000..efeb2967 --- /dev/null +++ b/qrencode-win32.patch @@ -0,0 +1,243 @@ +From 261d830b9b4126d76519db0e6b6b51b5a730eb40 Mon Sep 17 00:00:00 2001 +From: Andreas Traczyk +Date: Tue, 4 Dec 2018 17:42:43 -0500 +Subject: [PATCH] b + +--- + .../vc8/qrcodelib/qrcodelib.vcxproj | 129 +++++++++++++++++- + 1 file changed, 125 insertions(+), 4 deletions(-) + +diff --git a/qrencode-win32/vc8/qrcodelib/qrcodelib.vcxproj b/qrencode-win32/vc8/qrcodelib/qrcodelib.vcxproj +index aabc6b6..8d8293b 100644 +--- a/qrencode-win32/vc8/qrcodelib/qrcodelib.vcxproj ++++ b/qrencode-win32/vc8/qrcodelib/qrcodelib.vcxproj +@@ -5,45 +5,84 @@ + Debug-Dll + Win32 + ++ ++ Debug-Dll ++ x64 ++ + + Debug-Lib + Win32 + ++ ++ Debug-Lib ++ x64 ++ + + Release-Dll + Win32 + ++ ++ Release-Dll ++ x64 ++ + + Release-Lib + Win32 + ++ ++ Release-Lib ++ x64 ++ + + + {9A90BF5C-84B0-41F6-B83C-C20EADC1F46C} + qrcodelib + Win32Proj ++ 10.0.16299.0 + + + + StaticLibrary +- v110_xp ++ $(DefaultPlatformToolset) ++ MultiByte ++ true ++ ++ ++ StaticLibrary ++ $(DefaultPlatformToolset) + MultiByte + true + + + StaticLibrary +- v110_xp ++ $(DefaultPlatformToolset) ++ MultiByte ++ ++ ++ StaticLibrary ++ $(DefaultPlatformToolset) + MultiByte + + + DynamicLibrary +- v110_xp ++ $(DefaultPlatformToolset) ++ MultiByte ++ true ++ ++ ++ DynamicLibrary ++ $(DefaultPlatformToolset) + MultiByte + true + + + DynamicLibrary +- v110_xp ++ $(DefaultPlatformToolset) ++ MultiByte ++ ++ ++ DynamicLibrary ++ $(DefaultPlatformToolset) + MultiByte + + +@@ -52,15 +91,27 @@ + + + ++ ++ ++ + + + ++ ++ ++ + + + ++ ++ ++ + + + ++ ++ ++ + + + <_ProjectFileVersion>11.0.50727.1 +@@ -70,11 +121,17 @@ + ../.build/$(ProjectName)/$(Configuration)\ + true + ++ ++ true ++ + + ../.build/$(Configuration)\ + ../.build/$(ProjectName)/$(Configuration)\ + false + ++ ++ false ++ + + ../.build/$(Configuration)\ + ../.build/$(ProjectName)/$(Configuration)\ +@@ -104,6 +161,26 @@ + MachineX86 + + ++ ++ ++ Disabled ++ .\;..\qrcode;..\qrcode\png;%(AdditionalIncludeDirectories) ++ WIN32;_DEBUG;_WINDOWS;_USRDLL;QRCODELIB_EXPORTS;HAVE_CONFIG_H;%(PreprocessorDefinitions) ++ EnableFastChecks ++ MultiThreadedDebugDLL ++ ++ ++ Level3 ++ ProgramDatabase ++ ++ ++ libpng15d.lib;%(AdditionalDependencies) ++ ..\qrcode\png;%(AdditionalLibraryDirectories) ++ qrcodelib.def ++ true ++ Windows ++ ++ + + + .\;..\qrcode;..\qrcode\png;%(AdditionalIncludeDirectories) +@@ -124,6 +201,26 @@ + MachineX86 + + ++ ++ ++ .\;..\qrcode;..\qrcode\png;%(AdditionalIncludeDirectories) ++ WIN32;NDEBUG;_WINDOWS;_USRDLL;QRCODELIB_EXPORTS;HAVE_CONFIG_H;%(PreprocessorDefinitions) ++ MultiThreadedDLL ++ ++ ++ Level3 ++ ProgramDatabase ++ ++ ++ libpng15.lib;%(AdditionalDependencies) ++ ..\qrcode\png;%(AdditionalLibraryDirectories) ++ qrcodelib.def ++ true ++ Windows ++ true ++ true ++ ++ + + + Disabled +@@ -137,6 +234,19 @@ + EditAndContinue + + ++ ++ ++ Disabled ++ .\;..\qrcode;..\qrcode\png;%(AdditionalIncludeDirectories) ++ WIN32;_DEBUG;_WINDOWS;_USRDLL;QRCODELIB_EXPORTS;HAVE_CONFIG_H;%(PreprocessorDefinitions) ++ EnableFastChecks ++ MultiThreadedDebug ++ ++ ++ Level3 ++ ProgramDatabase ++ ++ + + + .\;..\qrcode;..\qrcode\png;%(AdditionalIncludeDirectories) +@@ -147,6 +257,17 @@ + ProgramDatabase + + ++ ++ ++ .\;..\qrcode;..\qrcode\png;%(AdditionalIncludeDirectories) ++ WIN32;NDEBUG;_WINDOWS;_USRDLL;QRCODELIB_EXPORTS;HAVE_CONFIG_H;%(PreprocessorDefinitions) ++ MultiThreaded ++ ++ ++ Level3 ++ ProgramDatabase ++ ++ + + + +-- +2.19.0.windows.1 + diff --git a/qt.conf b/qt.conf new file mode 100644 index 00000000..7bbb77fb --- /dev/null +++ b/qt.conf @@ -0,0 +1,4 @@ +[Paths] +Prefix=./ +Resources=./resources +Translations=./translations \ No newline at end of file diff --git a/ressources.qrc b/ressources.qrc new file mode 100644 index 00000000..1093bde9 --- /dev/null +++ b/ressources.qrc @@ -0,0 +1,111 @@ + + + images/icons/outline-info-24px.svg + images/icons/baseline-camera_alt-24px.svg + images/icons/baseline-refresh-24px.svg + images/jami_rolling_spinner.gif + images/icons/baseline-close-24px.svg + images/icons/baseline-done-24px.svg + images/icons/baseline-error_outline-24px.svg + stylesheet.css + stylesheet.linux.css + changelog.html + projectcredits.html + images/ajax-loader.gif + images/default_avatar_overlay.svg + images/FontAwesome.otf + images/logo-jami-standard-coul.png + images/qrcode.png + images/jami.ico + images/jami.png + images/spike.png + images/waiting.gif + images/icons/ic_add_black_18dp_2x.png + images/icons/info-24px.svg + images/icons/ic_arrow_back_24px.svg + images/icons/ic_arrow_back_white_24dp.png + images/icons/ic_arrow_drop_down_black_9dp_2x.png + images/icons/ic_arrow_drop_down_black_18dp_2x.png + images/icons/ic_arrow_drop_up_black_9dp_2x.png + images/icons/ic_arrow_drop_up_black_18dp_2x.png + images/icons/ic_arrow_forward_white_48dp_2x.png + images/icons/ic_arrow_tab_next_black_9dp_2x.png + images/icons/ic_arrow_tab_previous_black_9dp_2x.png + images/icons/ic_block_24px.svg + images/icons/ic_call_transfer_white_24px.png + images/icons/ic_chat_black_24dp_2x.png + images/icons/ic_chat_white_24dp.png + images/icons/ic_check_white_18dp_2x.png + images/icons/ic_clear_24px.svg + images/icons/ic_close_white_24dp.png + images/icons/ic_content_copy.svg + images/icons/ic_delete_black_18dp_2x.png + images/icons/ic_done_white_24dp.png + images/icons/ic_exit_full_screen_black.png + images/icons/ic_folder_black_18dp_2x.png + images/icons/ic_full_screen_black.png + images/icons/ic_group_add_white_24dp.png + images/icons/ic_high_quality_white_24dp.png + images/icons/ic_mic_off_white_24dp.png + images/icons/ic_pause_white_24dp.png + images/icons/ic_pause_white_100px.png + images/icons/ic_person_add_black_24dp_2x.png + images/icons/ic_person_add_white_24dp.png + images/icons/ic_phone_24px.svg + images/icons/ic_photo_camera_white_24dp_2x.png + images/icons/ic_baseline-search-24px.svg + images/icons/ic_send_24px.svg + images/icons/ic_send_white_24dp.png + images/icons/ic_settings_white_48dp_2x.png + images/icons/ic_share_black_48dp_2x.png + images/icons/ic_video_call_24px.svg + images/icons/ic_videocam_off_white_24dp.png + images/icons/ic_videocam_white.png + images/icons/ic_voicemail_white_24dp_2x.png + images/icons/round-add-24px.svg + images/icons/round-arrow_drop_down-24px.svg + images/icons/round-arrow_drop_up-24px.svg + images/icons/round-arrow_right-24px.svg + images/icons/round-close-24px.svg + images/icons/round-edit-24px.svg + images/icons/round-folder-24px.svg + images/icons/round-remove_circle-24px.svg + images/icons/round-settings-24px.svg + images/icons/round-undo-24px.svg + ../lrc/src/web-chatview/chatview.css + ../lrc/src/web-chatview/chatview.html + ../lrc/src/web-chatview/chatview.js + ../lrc/src/web-chatview/jed.js + ../lrc/src/web-chatview/linkify.js + ../lrc/src/web-chatview/linkify-html.js + ../lrc/src/web-chatview/linkify-string.js + ../lrc/src/web-chatview/qwebchannel.js + ../lrc/src/web-chatview/chatview-windows.css + images/icons/round-check_circle-24px.svg + images/icons/round-error-24px.svg + images/icons/round-save_alt-24px.svg + images/jami_eclipse_spinner.gif + images/icons/ic_hide_password.png + images/icons/ic_show_password.png + images/icons/baseline-desktop_windows-24px.svg + images/icons/baseline-people-24px.svg + images/icons/round-add_a_photo-24px.svg + images/icons/ic_mic_white_24dp.png + images/icons/icon-keypad-24.png + images/icons/ic_play_white_24dp.png + images/icons/icon-keypad-24-2x.png + images/icons/ic_voicemail_black_24dp_2x_.png + images/icons/av_icons/delete-24px.svg + images/icons/av_icons/fiber_manual_record-24px.svg + images/icons/av_icons/play_circle_outline-24px.svg + images/icons/av_icons/re-record-24px.svg + images/icons/av_icons/stop-24px-red.svg + images/icons/av_icons/pause-24px.svg + images/icons/av_icons/send-24px.svg + images/icons/av_icons/stop-24px.svg + images/icons/av_icons/mic-24px.svg + images/icons/ic_close_black_24dp.png + images/icons/extension_24dp.svg + images/icons/settings_backup_restore-black-18dp.svg + + diff --git a/ringtones/Makefile.am b/ringtones/Makefile.am new file mode 100644 index 00000000..64fab830 --- /dev/null +++ b/ringtones/Makefile.am @@ -0,0 +1,5 @@ +ringringtonesdir = $(datadir)/ring/ringtones +dist_ringringtones_DATA = \ + konga.ul\ + default.wav \ + default.opus diff --git a/ringtones/default.opus b/ringtones/default.opus new file mode 100644 index 00000000..c3c0a807 Binary files /dev/null and b/ringtones/default.opus differ diff --git a/ringtones/default.opus.LICENSE b/ringtones/default.opus.LICENSE new file mode 100644 index 00000000..98b99bfc --- /dev/null +++ b/ringtones/default.opus.LICENSE @@ -0,0 +1,4 @@ +Original file name: 171324__swidmark__ringtone.wav +Download location: https://freesound.org/people/swidmark/sounds/171324 +Uploader: https://freesound.org/people/swidmark +License: CC0 1.0 Universal (CC0 1.0) (https://creativecommons.org/publicdomain/zero/1.0/) diff --git a/ringtones/default.wav b/ringtones/default.wav new file mode 100644 index 00000000..f68346e5 Binary files /dev/null and b/ringtones/default.wav differ diff --git a/ringtones/default.wav.LICENSE b/ringtones/default.wav.LICENSE new file mode 100644 index 00000000..98b99bfc --- /dev/null +++ b/ringtones/default.wav.LICENSE @@ -0,0 +1,4 @@ +Original file name: 171324__swidmark__ringtone.wav +Download location: https://freesound.org/people/swidmark/sounds/171324 +Uploader: https://freesound.org/people/swidmark +License: CC0 1.0 Universal (CC0 1.0) (https://creativecommons.org/publicdomain/zero/1.0/) diff --git a/ringtones/konga.ul b/ringtones/konga.ul new file mode 100644 index 00000000..2191150e --- /dev/null +++ b/ringtones/konga.ul @@ -0,0 +1,11 @@ +~~~~~~}~{|~u}w~z~ziukizrj޽  +I/$%  $5Ȭ "A/hnѡPD? ;MHů;1!"#.cLGZ<%.=ϾO0,,%'/Cཱུ\7.$"$))+,//58AA<2//4;>>=6/*'""$*,.+&"!#(++--+++*-.3>QSndf\D91//.)'*.26BA84.0/5;<41;>BEAOp˼qѾȻeXL>B]OD;36//153/00,)).N]SNNTVTID@GKOFbFD??=<>FO`nJCCENLGbmWJ>EIWWX[`L=>:9<=Mr¿̻LK\_SGE@GF_ürW`Z<77AMo`REOkcbf@?FJOMKRPN^`e}YXgpNF:7>FGGDTuɾe\vh__\RSE?:9=::=U{^gi\m]ZjVM]dNLSloYJGIUR]unkʼMJA<;=EMY\JG?@GFMaĽNKFIPV^zne]tl^dkbUKD>?IR[ZY`ov}tviXU^mÿd\iprX]\XPK??>>===??CJSghou^sy[W_gVWY[\n˾YOqjXUZ^QHDHIKNdnivb\a~YZWX~_YW_dfWSczrk\dqv`]_geo{bVQOLKO_j^WSNDCJKMJMSsTMGHlq]Xl\WZTKGGJJKLNMPRLNVVOJJORU\ſpm]SXXZWNMOX\_e`ZXajcZSOQ_kWQKMQOPR_da^Z_m_XOMMRZYZk{inxj]ds}yrjd]cdaTTKE>ACGKS[UOO[mzc\Z_z`YMLU[ksVMFHGHIMPYi|ojUOLNQOJKLKLR]c]VUSVTW[etxhiqy؜407=>LS5JU( ')1;$& 03˟L!#,.6-$NM.*8ì0!:&$'GD))7K9ϫL(&*+8ӾH>6-3HK:)#%0r0$#$1q?&$.=M﫠?-,+->ƫȪH/.:Ͷv.-:lI-.78IƹPE7469==61/358Ga~?/$$+5XϻYC<=T޼ORTuϿ]@?J_ƼC:55;99IohdK@FFLYlO9568;;FZ̾QGDEI߿þf¾jUM\ʽYOQTR½wMINZ91..28QU<-.07QQB9<>EhUJ?9=bµ<89=øeOJD\fh`UjļNHJKX¼KC87:MjKBFBLRTL>?D]vDB>>BOŽJ;78;I忲K<CN\hga]_O_[KIM^gIMKK\Ƚ`^lmlɽ_HHNlgOMDE\ndvfnxWH?=7103EUcMCDJWZf_bapk|fgK?=DL_=4:=FOYOSQqټ˼ƿX5--5ALǽk_D1+('(,6?KILG?;;;99:<=><;?ADPay^XID>=Lc½ĺey~žo]PQ[}tC<78:=S'# + 8N $RE50m& /-FTU(&#ҦP3<)$*\Z08:C()/+ />*,%$A鷲Si۬za/*3<=,!(318ZU]UK@/..23))$ !&# %# "%=ͽnY]imϴ·l9=H?=Yо¹jLA<==IYnIoUA>@>?[LOUUrgdOK?KMlKS>=D[F;?;?c\ZǺٿpƿIOCSwN91-@_osGX@:7;=:;:PFKERg]J>ʹ~LMb\\X^W|XbW`TNYiWU`kLJ?768O;MDB5,*$!"'0>@KiμŷY>:64;:7779:==><;@@AAFo\zxfYQLKISOU_{{ddZUhvdZNK?NqoldMLY\ZzRNLHLN_ZOHFMOfONINRVLFIMSyh`nl_[F?ALYusenxgRik_ZlvklûǾ[\[hcJKTQMRRyucZUURKKPq_cu_Wk\LJTnxUaƾ{|mqozOMR[Rcn[KFBFMOMLSY`^]][SJIM]op~~ȿ_Zds{[clONMWkWTWfw_^YZTUT[Z|q]\gZIIP^W^]ZQNNULPY]pp]VZiz{zhypyma__WUNP[mrzn^[neSKQW_b\VNMIGIRTPPJHKPNJJO_SPS[XUPQU[Z`iknm`VYYellf]_`eZZ]ZjRNMKLNTVagf^c_nx_Za_pvjdkkztnx|b_m|e_jeb^VKIIKLMLMU][kmjjdzbftrb[]\XYTOORRRONMMPT\geiq}m\S]ir{^WX]tolj`ZVWWVPQ[_\[agai|}{ytecXVQPSSV[_YW[_][]jpwzomhssveYZTMOTWYY^k{zjfca\VXVSVVVWWYXRZ_YXTWZ[Z\_hklsnkc]_binsxjnpnh``eovjb]XX\bihgoe_c`iqkhdcoux~}z{oeklm`]Z[[^bb_b^VTXZX[eb_^uuvyklyk^YTX\kyjc^WXXWZ]]`kyxxrjysmmxœ2/LV:;$ 60) + +#ɶ! + #3їf&8F<+&6ʷ0*:/]$"'*:JϬTFɬ?E-'<8RQ4.&-79Ǭ@+#"/E챞B.=B8Ȝ/97%)<ȪU/*(,=VSH>^U:37/-,05-,-/,.8O>@˲ON:BOENúX?6/,+3XϽ[PF޾GBce.+=W𿭧D;436=X{SLFC852((/:ȱX<--;FmyŴi9/..9Oī{+*+2FϼoLB@58Aį5)!$3MȸU:.-..03@_hF:-.6N̽JE?89=\ļn_>>N÷kLC?GRd=>HQsŹνk<47AlɹMFEV^86=DSC4<CUƸ]JCNڷJ84=nY9..9Zo<9?EJ_pMA;5:QϼI?<9HtjB:/.9WƼVG=;ALngPcȼzC>;EjSLILKI`KHNvbE=9;FA55FbM5,*0>˹OI[klR>;>JvϺ^A38=BԼJ:L㾾VB426;R۽ND>EoſO=98=L]żZXS\oVQRIEFMt¾ZB>K^L768C_tGD==??Mt\E>?@@D\PF>?FLYl^XY@87?LžTLFHR\eSMS`wuqJ?:?IƾO>65?Nlx`D=>Bj¼D@CNTJGMe[XPc^KJIKO_VNMSRP\peVMN[{~_^_SMSiļtIFM[}zmlbUURbmYOLOcm^SOMZZmzeYfZGBFMOZnf\POKP[YSJMfOJHN_lsaQMUpkVPSVgovZSQRVWhjXTMKOMWo|oYTOQX`lh^[_kxhn^OMVi{SWh[VU_|VNJLTkona\\]i{_\]ieZZdredYSQ\hk}vigc[NN`h[ZckTOKViclkcNN[cleszePV_hoi\`kjoicP^\WYU]Xodޮ +/"2  >6 kNO'*' 0$'2E:8i˽eO7CgƼl¾󹹬ŽQOgf7.=<>[KE0(*+?V??GC@N|Ŀzúμ׿ڿe_XbW?@F\YmpQhwnA;?@C551//:CLINBK=C@;BEYh;Hfx>98GZUĽƽueoII?JwhYNNgcQ`T[hICIMzo[GF=HIIYiSHR^TH227O`[\]OuvYJEONYT[ozoOYQ]^]ɺĺfWOLA@78473765<;>@BB?[Kƿ¸ɻWZKBJ>EKMGCB69ENQKCBRan¼¾]YP]e[G?@JLGjI?:AOy`hwmy]n]`mݿ`ŻZ[NB>ORaNF>78;DED?@HDIKNyt»ľþp[INSNLAGDCHNZh[XaTURgwYV[k|blYO^g{s\SS[^^XRONPac^YNVMT\dyq[fǿyhubZ^_l_f^cpZMGLKNPWXJGNZYveykrr]_od_hofr_a[_k`d\[NMVoidnzljywl_TQU[jpq_W\TYWYYW[OPX_vsppvqjkp`bcjf`YMONKMT]TLIHSV]YUWez~^Z^jYY_ZY\[_YT[WYXYd\gbfgWgyndmshh^^]tqmt`ZZOTT[]PPKVXZclrkjͥICLI,&$$&$ܭZF~ô4$ "$'-&$)6=ũ]-))2浤L('*54)06ֽL/ (/N괶.#%%5èN*+/AC,)):Oj<3GE. $'7KbGLHC㻵JB;00<ȬYKO>58=Qjuí:,()),:u̹EE\ɾX1-1;>/1IίH6<>=qؿTF>89BOTM@<>FMb¼F/%&5OwH;=Rپa?0./9c]PC>BJ`ZFG\½f@>K绯d<867:DȺbiUA;@UQIBGlW?619PǾKJNX`bMRTznKFJVžvJLD?ESs]XWWE=>?GaǸM@>:<>GdpXMAFLXʿ]`OF>CMch\NIV|LHLUWTU]nVV\WWrL=8:Hl`THFKSb\QLLh^IDDKTd]OJFELW~ZLIIFLVmKGGJYlx[MLMVk|eSMO\mof^[[\d_NFIL[uVEAAGQVemjURNLOT_\QPTmzmljomcVOIHN[gROKIMVaVVYVj^OHISgo]V[lkccfkmZTNOYjr[TQVZovvf]PMQWki[POQUZgxlmmgfadt[TOT^oc`_[ZjkZTUV_hmXRPS^c|ohc``_i}ia[Z_lwhj__^_djwga[_v}nooh^\]]]_xwcUOMOUan|utsnfjg^[[ekdbejt|qlfb^_dmnhnd[Z^ywz{jd^^mi^_^TWcr{s~viihftnfpm^daƵfm  !Tn.*'./*"+,%')/B<&P- *8;PC50)""IļB2*%)Fg6)(7iU>-'+-( &-/IN>+% $&)%&&)+.:ر[<-()*)-47*!#&/63*%!$!!! #'4Enǿʹ_sK=,% #""!!(-9HU_NKXWVKMZǰʿcI::40///+(&""(/250***+-../3364303/.39743.1:=Wt~~HSeGB@ERQY^V^NQLWSkw_O\REFF:1102029:<=FUUID@=<>>CYXw\MTȻȽ¹ĻǾ|S:658>CDHEGMG==KPONMTxhA95467<>ArŻǼTL`ŽWKLQX~nKFJKMGCKMHJACUnb\TY^VE<;98AAPfǽcIIi~TNMMWǿh[M>=>NxlpVQFKYVZm]JGECA?DBACPYk\OQg}ZKC>CMPUYedwƽu_rϽd^uaUNPKEC@>>><99?\w_f_PSSXYbrb_cYRWowdPNSj|r~XOKECAFEOSQLE>=CBDDBCLNbjYNKKTZbrus``|f\MEDJMWd`^oyoq]VZciƿ^XQ^kn^RRPPNLFFJIA??@??HL\avm[_ne]go|sWOR^jngZVOSYXTRVTMMTZ\YOOMU\lwt_TV^uf_ipoytvztdUTONWbvlWXOJJNNONPYccfWJGGKpxuwcYY[pwc[`VOSSU[]\acee[^_\VXXW]_ikjjdX]efi]SPQR\e`\ZZ_^YUPS[ur^SROQVVXX]][[\nzkf[Z\]b`r^XZ^bkolhn{|eYWNEDEFJQ_Z[\p}vh``_}whqzg^USZhxn_RURQUW[jvlnyrn]VTUSROKLMNU]hpwg\\^ZZkvto~kuuzϯU4),O@* ȱZ6+$5%! 7m.'2f!D"@8-O$$Qâ^:1,(9K)98  `R( *CB]!*E˪0!(M/"*=V&%(+E8,$")+'" %)3LW! 2¼xN+%*;K.+4OȲȾR-,<ʩo(4[@;-+,&(*))5^:'# 'WǹHOʺýűYE8:Zǽ]>:8?>1%! %*7A|5&%,38>?NYD=98JժVJ8/:?SŶ:=1,&(9JɿK?80,2GWZ8/5C^g:.244>Žn?JFCMZɼ?3-?嶫x[YaUODLS^UK>GZVA=L]?%+@ӻM.+),=H[\νD::EKH88?Kȯ922=λbVt˽@=@GD=>aͿeN<.&$&-:?Uo̾zSFFUzL:8>kȿvB=?9=cܼ[MYLIO^ҹ?/0:I̽WC97>xbOE>4,)*8BTn»E,&#).4CXZIHFGKMλKBBMH825K7,())*7;BB:-$"6T;;=<760+%$)*8ZCFմɽ̼I/,*+.3CM[>/+**/57>>92.035:>A0,('$'+18DIR|G3'"!#'-:>KI=AADOoþķzG?<958DU`D4.,-279::;??;941/1;943568>VtL><;>Nzʽǿ^NLSTo{YMMRSH?;6788?HHDFB<7/-04;8:=FKMXZjxoǻgUUW[cziWB=98=DECBC<;@EACEEDDFFMMYmt}xufZXZ\TOZyk¿XR_yszZ]acZPOHDA?DHQ]ŴLOsXx.))'')3,(*23///QʰϷTU}@62211666=NºU@?>BƵd=<;80.7E_V>81/339:BLf^Vlo_f˻ǾjXVb]M>=96;>EJUk˿L?@XԾm_^RD>BDA@=<<)"$*&$&%-::gϺI4%$&(#$%& (.?CE::VCA0,2451,-#% "&%)1*-=FT=/3߲deIJBA;LBFWHVzyi=:/3+)7:<:?1313:49FUR=9:49Gŷ̼kwɭW;.4I?GKMND:3EA9]5G=7ceZUXHgijW^WPCoI@4(3/.342/SQL\;807BVB׾Ke_EHB?8*!#,2/$-&(*,,+6ǹ˯sPX7CH:;>7-+&,'*,2CIDE>1.,11C`\OBDO]yjƼWLXNK^OOIM?60,--4=KLNEIJLSNU]QzɾÿþoeO_NW]SRE;533266=@TW`}cHGFZ~Tb_qb]MA@CEFBBEJKFKVQ|YEPUȺghXVKHHDE?;24=BK_>:>EdXSfɴUJKRÿVQSXSEE[ll[KCEFOT_MNYY}_{}ok^LGJHIBHTROan[SVi\Xc\mUOOKLRQLVZ[]c|exe[KGIG]mi]okrcMNdnabdvfgu|nc`^g^ankbo}jxaXUZSX|uqi]neUohc^XKILU^afiPLDCN[_RYj``ght^aZXNTLGE>?EHV\f~VROO]lhu|wm`nq_g_\KKKDEHJEBDEQ_jmc^ytϿceo_MMKIGMMLIKKIMOSNLQZ_mf޿ʹ"+-*.+Jʦ/%+,*$#*4( ('$ (9i-($*=ENΧEBK9,  &>|nlѿe?Kݻn?9473553*#!&*+**,-.45504:>=>GuɽebJNTWUMA846=FKLF=3-)'$$'),*,+)''*4?FI?HSiſȽk_OJ>8>M]dO@@C??FRVW^B:9:?IS__K;69=M\_OUMRYI=9AAJKK?=968>>?@HM[dcgYH:97:@CWtj_^l^»;fH@@FMLKIDB??>AEXg{fp_QGCCKPSWSW^UI=99??H_k]fmjZMIGGDDKNOYYb[Y[VVZOIHHKLGC@@FMPkNJGBCDJL]nfdb]W^WLLRZ¾lnnw~c~|gWOOR__YVXQLLE?BEJNYWTPLIJMN^akemo{Ƽhjwvk}|jRNNONKKJKOQv|oeVQOQ_t_RNSSVTNJKMOQRUVSSORQUZfaWSOLMR_}fNJHHIKLLJFFFA@BHPXaUUcfj`ooihi~o_Ykp~icaWUX^ZZ^^ZYSNLMLHDFIKRU]^svk`[[qf]\Y[fye_ZZbiimifd^_]]a^YX[_mtg_]_q~sm{lbimgd^]\]kmc[WSKILNOYbowqv{qc\WQNOW[k}~^TMIGGIKOSX^bffrvmz_^ZY\YVY^\bginj_YWZYYa^jioin\]XPngd[jƒ7..rJ{:ŗA:L:=F*# +%(2[ +[=, " 쐑 ̔R( #N(1F$ 6ī,'-:L-&*&,Ǩ:A, (8J>J/+- ,XߪƻR,!.5+%!/E<%&-I[?2/>W{$ WU9"&>1"ޯP5+:mr:8Oĸ;+,?m$)8S74HL/#%=庿6))DS@FYM?N]>../3EUrB60>_J8?DBG\̶KIJNJ953>/'(3EiŹdD-,1]=#%8b,##-a\H:$%(-C֫b;,&&<{MTI>UľA5=QQ5/5<ϳt7268AI{~B>IzIMmYmŲX5'*5V?376@LnĺN4,;?KAD_θ2+&)>Wnv[H?@@̷J4/4A˵s;4>Hɺ`3+(1=IYʿSHReJ3-/EɯP84//:IںEA:773/6LʵdE=+)8ؾU>77?Lb˿];/$#->nR=0.68@Iba_VH@9q.'%(5K϶MSJ>=?40/3E߷N,&).=b>48O|žE;I`ntÿO1)(-6cųT>505Bs{Z^eiQ<:Gwm;804;EʽG<7558D|ɿP>85/2<˸=527?I_AAS]ɻF?9LƻQ?79?XdWJQxm_U[YoG?==JSĹE<9?E_i`eTKQWjpZNJKW^liVMO`TQLFRmrH>>FP\Y[SMZ_KKMOUdm˿]GBCQ[hTKDBFZtZFCDIfoOLHHNVux[MEFPnl\TXn]XW_]b_mM@??CJbdituj\ON^SMDBLg_^UY\bwzlj_Z]ahnw]WisNR_rXHDIRlq^SCCKVfnwtf\ZUYiyePTUVayqq\SZQMRYomd^]SNsnT[_N^nܟ 짶>[! + m&ܬ?:)K! 'BE/7F+*׺ղ^43CXױS*'GF+8BAʼ^!'' 2иж~=<3&( #,(%),2>պJMUpJ>;><50+-)%+&1C}ƻ|ȲpNL=30401.(& #5>8?A98>ݫmQOaRn60('""%().+(#'3CFK=6:48H亭ȿgL79=9?62'%""-76.3*/-0A;NaȿlBET;;:<3-.-'!&#$.(+)'+(++++=OMQI?>JX]ź]Z[IKbK3LIDMG;8ɺooF\ĿɮĽ}=?@5AQC//()&##)+,6;?F;4=K϶ſSVlC85=G<:1./2/53//08:20,/;oĹϼȸdhOA:I?/41(,,-+,,61;9>FD:4:fisźXʽX?::HFQNG799083=:JLPG:69@LLOJ>AOWGF[Lr~fQG}ԿcRھοXMAf¿OqSOWYcdbSMH<<@FOZLGCMSk_cHMĿZimhUq`\xO@=;:KFNGH>845<<8:DVmgĻ»Žo]zhQECWM[QVPKMJ@D?BW~f_ORaTunVUPObX]irbhv~ZKORLLGIMOWMMWboSǾüR@=<>E^L?:8>CDaI=8>JoMKOf|ih\PNZfڿZamƼg\TJcmrVUMHLVVVMNgstjal{dI>@CIELXQEEGBKIKJGGKYn|ͽoeSZSdg_TXYhVPY^V[ql]^YQWPKITYQX\rff^Y\cye^ee_oyhvg}^Snrk`hhfUKLNJNOV[Z\UHHC@JZXOY\utirj`lYXNHHJNJObd|b[X^~od__TTNOPROFHJGHOWNKKFMY[\Y]v]^n]XSNQUZ\SQPMMLMNNSlvziQYTgh^Y^{ggnf_`dB9>[QS<(!#%i&%%&/) $2:ϭ6"*4ǭ2'/}-#-2ί9&&+:[@%%'>E().9?$!%,A˭90OM3#%-.Dϴ]ٳI95)*4I:8<վ\9,/7>hQȲP,+,,3P˺zeָ<./:V.&(4vY:.066L]J=9;Dh[GMV{߹C0$&6MbT_vV9/0>V¹M=/,.5aƼVBKñw|øC@WθQ:.,,-9VWJOB529IMF@G񴬩F;7<ĿOMNXgp~_LHJMNSULDEW]HIFCJfɾvLB?BKYĺK<:68>DLXg\maOFNVkWGI<:B^½[B9:JySIA?FVƾ^LEHl̾]TT_cgǾ?866C]H>;=DloWSUnLHIRs^WlSC>>HY^¼OQ_kNJKexVMJA@KTþ~XO@???BIc|XBAN]lYMGNYatZK?:68KdTLGOQ]hzXJEKVWMIGIMN\VOV^inpaRNKITiLEOp[>::=Nn»xrh[ONI?::ANzjN;9=BOLGKVkbwt}NJUeMDBDJUaVNRON[cjllYC<; + * Author: Anthony L�onard + * Author: Andreas Traczyk + * Author: Isa Nanic + * Author: Mingrui Zhang + * + * 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 . + */ + +#include "accountadapter.h" + +#undef REGISTERED +#include "../daemon/src/dring/account_const.h" + +AccountAdapter::AccountAdapter(QObject *parent) + : QmlAdapterBase(parent) +{} + +AccountAdapter::~AccountAdapter() {} + +AccountAdapter & +AccountAdapter::instance() +{ + static auto instance = new AccountAdapter; + return *instance; +} + +void +AccountAdapter::initQmlObject() +{ + connectAccount(LRCInstance::getCurrAccId()); +} + +void +AccountAdapter::accountChanged(int index) +{ + auto accountList = LRCInstance::accountModel().getAccountList(); + if (accountList.size() > index) + setSelectedAccount(accountList.at(index), index); +} + +void +AccountAdapter::connectFailure() +{ + Utils::oneShotConnect(&LRCInstance::accountModel(), + &lrc::api::NewAccountModel::accountRemoved, + [this](const QString &accountId) { + Q_UNUSED(accountId); + + emit reportFailure(); + }); + Utils::oneShotConnect(&LRCInstance::accountModel(), + &lrc::api::NewAccountModel::invalidAccountDetected, + [this](const QString &accountId) { + Q_UNUSED(accountId); + + emit reportFailure(); + }); +} + +void +AccountAdapter::createJamiAccount(QString registeredName, + const QVariantMap &settings, + QString photoBoothImgBase64, + bool isCreating) +{ + Utils::oneShotConnect( + &LRCInstance::accountModel(), + &lrc::api::NewAccountModel::accountAdded, + [this, registeredName, settings, isCreating, photoBoothImgBase64](const QString &accountId) { + QSettings qSettings("jami.net", "Jami"); + if (not qSettings.contains(SettingsKey::neverShowMeAgain)) { + qSettings.setValue(SettingsKey::neverShowMeAgain, false); + } + auto showBackup = isCreating && !settings.value(SettingsKey::neverShowMeAgain).toBool(); + + if (!registeredName.isEmpty()) { + Utils::oneShotConnect(&LRCInstance::accountModel(), + &lrc::api::NewAccountModel::nameRegistrationEnded, + [this, showBackup](const QString &accountId) { + emit accountAdded(showBackup, + LRCInstance::accountModel() + .getAccountList() + .indexOf(accountId)); + }); + LRCInstance::accountModel().registerName(accountId, + settings["password"].toString(), + registeredName); + } else { + emit accountAdded(showBackup, + LRCInstance::accountModel().getAccountList().indexOf(accountId)); + } + // set up avatar pixmap from photobooth + QImage avatarImg; + const bool ret = avatarImg.loadFromData( + QByteArray::fromBase64(photoBoothImgBase64.toLatin1())); + if (!ret) { + qDebug() << "JAMI account creation BASE64 image loading failed"; + } else { + LRCInstance::setAvatarForAccount(QPixmap::fromImage(avatarImg), accountId); + } + }); + + connectFailure(); + + QtConcurrent::run([this, settings] { + QMap additionalAccountConfig; + additionalAccountConfig.insert(DRing::Account::ConfProperties::Ringtone::PATH, + Utils::GetRingtonePath()); + + LRCInstance::accountModel().createNewAccount(lrc::api::profile::Type::RING, + settings["alias"].toString(), + settings["archivePath"].toString(), + settings["password"].toString(), + settings["archivePin"].toString(), + "", + additionalAccountConfig); + }); +} + +void +AccountAdapter::createSIPAccount(const QVariantMap &settings, QString photoBoothImgBase64) +{ + Utils::oneShotConnect(&LRCInstance::accountModel(), + &lrc::api::NewAccountModel::accountAdded, + [this, settings, photoBoothImgBase64](const QString &accountId) { + auto confProps = LRCInstance::accountModel().getAccountConfig( + accountId); + // set SIP details + confProps.hostname = settings["hostname"].toString(); + confProps.username = settings["username"].toString(); + confProps.password = settings["password"].toString(); + confProps.proxyServer = settings["proxy"].toString(); + LRCInstance::accountModel().setAccountConfig(accountId, confProps); + + // set up photobooth avatar to SIP avatar + QImage avatarImg; + const bool ret = avatarImg.loadFromData( + QByteArray::fromBase64(photoBoothImgBase64.toLatin1())); + if (!ret) { + qDebug() << "SIP account creation BASE64 image loading failed"; + } else { + LRCInstance::setAvatarForAccount(QPixmap::fromImage(avatarImg), + accountId); + } + + emit accountAdded(false, + LRCInstance::accountModel().getAccountList().indexOf( + accountId)); + }); + + connectFailure(); + + QtConcurrent::run([this, settings] { + QMap additionalAccountConfig; + additionalAccountConfig.insert(DRing::Account::ConfProperties::Ringtone::PATH, + Utils::GetRingtonePath()); + + LRCInstance::accountModel().createNewAccount(lrc::api::profile::Type::SIP, + settings["alias"].toString(), + settings["archivePath"].toString(), + "", + "", + settings["username"].toString(), + additionalAccountConfig); + QThread::sleep(2); + emit LRCInstance::instance().accountListChanged(); + }); +} + +void +AccountAdapter::createJAMSAccount(const QVariantMap &settings) +{ + Utils::oneShotConnect(&LRCInstance::accountModel(), + &lrc::api::NewAccountModel::accountAdded, + [this](const QString &accountId) { + Q_UNUSED(accountId) + if (!LRCInstance::accountModel().getAccountList().size()) + return; + emit accountAdded(false, + LRCInstance::accountModel().getAccountList().indexOf( + accountId)); + emit LRCInstance::instance().accountListChanged(); + }); + + connectFailure(); + + QtConcurrent::run([this, settings] { + QMap additionalAccountConfig; + additionalAccountConfig.insert(DRing::Account::ConfProperties::Ringtone::PATH, + Utils::GetRingtonePath()); + + LRCInstance::accountModel().connectToAccountManager(settings["username"].toString(), + settings["password"].toString(), + settings["manager"].toString(), + additionalAccountConfig); + }); +} + +void +AccountAdapter::deleteCurrentAccount() +{ + LRCInstance::accountModel().removeAccount(LRCInstance::getCurrAccId()); +} + +bool +AccountAdapter::savePassword(const QString accountId, + const QString oldPassword, + const QString newPassword) +{ + return LRCInstance::accountModel().changeAccountPassword(accountId, oldPassword, newPassword); +} + +void +AccountAdapter::startAudioMeter(bool async) +{ + LRCInstance::startAudioMeter(async); +} + +void +AccountAdapter::stopAudioMeter(bool async) +{ + LRCInstance::stopAudioMeter(async); +} + +void +AccountAdapter::startPreviewing(bool force) +{ + LRCInstance::renderer()->startPreviewing(force); +} + +void +AccountAdapter::stopPreviewing() +{ + if (!LRCInstance::hasVideoCall() && LRCInstance::renderer()->isPreviewing()) { + LRCInstance::renderer()->stopPreviewing(); + } +} + +bool +AccountAdapter::hasVideoCall() +{ + return LRCInstance::hasVideoCall(); +} + +bool +AccountAdapter::isPreviewing() +{ + return LRCInstance::renderer()->isPreviewing(); +} + +RenderManager * +AccountAdapter::getRenderManager() +{ + return LRCInstance::renderer(); +} + +void +AccountAdapter::setCurrAccDisplayName(QString text) +{ + LRCInstance::setCurrAccDisplayName(text); +} + +void +AccountAdapter::setSelectedAccountId(QString accountId) +{ + LRCInstance::setSelectedAccountId(accountId); +} + +void +AccountAdapter::setSelectedConvId(QString accountId) +{ + LRCInstance::setSelectedConvId(accountId); +} + +bool +AccountAdapter::hasPassword() +{ + auto confProps = LRCInstance::accountModel().getAccountConfig(LRCInstance::getCurrAccId()); + return confProps.archiveHasPassword; +} + +void +AccountAdapter::setArchiveHasPassword(bool isHavePassword) +{ + auto confProps = LRCInstance::accountModel().getAccountConfig(LRCInstance::getCurrAccId()); + confProps.archiveHasPassword = isHavePassword; + LRCInstance::accountModel().setAccountConfig(LRCInstance::getCurrAccId(), confProps); +} +bool +AccountAdapter::exportToFile(const QString &accountId, + const QString &path, + const QString &password) const +{ + return LRCInstance::accountModel().exportToFile(accountId, path, password); +} + +void +AccountAdapter::setArchivePasswordAsync(const QString &accountID, const QString &password) +{ + QtConcurrent::run([this, accountID, password] { + auto config = LRCInstance::accountModel().getAccountConfig(accountID); + config.archivePassword = password; + LRCInstance::accountModel().setAccountConfig(accountID, config); + }); +} + +lrc::api::NewAccountModel * +AccountAdapter::accoundModel() +{ + return &(LRCInstance::accountModel()); +} + +lrc::api::AVModel * +AccountAdapter::avModel() +{ + return &(LRCInstance::avModel()); +} + +lrc::api::DataTransferModel * +AccountAdapter::dataTransferModel() +{ + return &(LRCInstance::dataTransferModel()); +} + +void +AccountAdapter::settingsNeverShowAgain(bool checked) +{ + QSettings settings("jami.net", "Jami"); + settings.setValue(SettingsKey::neverShowMeAgain, checked); +} + +void +AccountAdapter::passwordSetStatusMessageBox(bool success, QString title, QString infoToDisplay) +{ + if (success) { + QMessageBox::information(0, title, infoToDisplay); + } else { + QMessageBox::critical(0, title, infoToDisplay); + } +} + +void +AccountAdapter::setSelectedAccount(const QString &accountId, int index) +{ + LRCInstance::setSelectedAccountId(accountId); + + backToWelcomePage(index); + + QMetaObject::invokeMethod(qmlObj_, "updateSmartList", Q_ARG(QVariant, accountId)); + connectAccount(accountId); + emit accountSignalsReconnect(accountId); +} + +void +AccountAdapter::backToWelcomePage(int index) +{ + deselectConversation(); + QMetaObject::invokeMethod(qmlObj_, "backToWelcomePage", Q_ARG(QVariant, index)); +} + +void +AccountAdapter::deselectConversation() +{ + if (LRCInstance::getCurrentConvUid().isEmpty()) { + return; + } + + auto currentConversationModel = LRCInstance::getCurrentConversationModel(); + + if (currentConversationModel == nullptr) { + return; + } + + currentConversationModel->selectConversation(""); + LRCInstance::setSelectedConvId(); +} + +void +AccountAdapter::connectAccount(const QString &accountId) +{ + try { + auto &accInfo = LRCInstance::accountModel().getAccountInfo(accountId); + + QObject::disconnect(accountStatusChangedConnection_); + QObject::disconnect(contactAddedConnection_); + + accountStatusChangedConnection_ + = QObject::connect(accInfo.accountModel, + &lrc::api::NewAccountModel::accountStatusChanged, + [this] { emit accountStatusChanged(); }); + + contactAddedConnection_ + = QObject::connect(accInfo.contactModel.get(), + &lrc::api::ContactModel::contactAdded, + [this, accountId](const QString &contactUri) { + auto &accInfo = LRCInstance::accountModel().getAccountInfo( + accountId); + auto conversation = LRCInstance::getCurrentConversation(); + if (conversation.uid.isEmpty()) { + return; + } + if (contactUri + == accInfo.contactModel + ->getContact(conversation.participants.at(0)) + .profileInfo.uri) { + /* + * Update conversation. + */ + emit updateConversationForAddedContact(); + } + }); + QObject::disconnect(addedToConferenceConnection_); + addedToConferenceConnection_ + = QObject::connect(accInfo.callModel.get(), + &NewCallModel::callAddedToConference, + [this](const QString &callId, const QString &confId) { + Q_UNUSED(callId); + LRCInstance::renderer()->addDistantRenderer(confId); + }); + } catch (...) { + qWarning() << "Couldn't get account: " << accountId; + } +} diff --git a/src/accountadapter.h b/src/accountadapter.h new file mode 100644 index 00000000..7ebc19a6 --- /dev/null +++ b/src/accountadapter.h @@ -0,0 +1,128 @@ +/* + * Copyright (C) 2020 by Savoir-faire Linux + * Author: Mingrui Zhang + * + * 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 . + */ + +#pragma once + +#include "qmladapterbase.h" + +#include +#include +#include + +#include "lrcinstance.h" +#include "utils.h" + +class AccountAdapter : public QmlAdapterBase +{ + Q_OBJECT + +public: + explicit AccountAdapter(QObject *parent = 0); + ~AccountAdapter(); + //Singleton + static AccountAdapter &instance(); + + /* + * Change to account corresponding to combox box index. + */ + Q_INVOKABLE void accountChanged(int index); + /* + * Create normal Jami account, SIP account and JAMS accounts. + */ + Q_INVOKABLE void createJamiAccount(QString registeredName, + const QVariantMap &settings, + QString photoBoothImgBase64, + bool isCreating); + Q_INVOKABLE void createSIPAccount(const QVariantMap &settings, QString photoBoothImgBase64); + Q_INVOKABLE void createJAMSAccount(const QVariantMap &settings); + /* + * Delete current account + */ + Q_INVOKABLE void deleteCurrentAccount(); + /* + * Setting related + */ + Q_INVOKABLE void settingsNeverShowAgain(bool checked); + Q_INVOKABLE void passwordSetStatusMessageBox(bool success, QString title, QString infoToDisplay); + /* + * conf property + */ + Q_INVOKABLE bool hasPassword(); + Q_INVOKABLE void setArchiveHasPassword(bool isHavePassword); + Q_INVOKABLE bool exportToFile(const QString &accountId, + const QString &path, + const QString &password = {}) const; + Q_INVOKABLE void setArchivePasswordAsync(const QString &accountID, const QString &password); + /* + * lrc instances functions wrappers + */ + Q_INVOKABLE bool savePassword(QString accountId, QString oldPassword, QString newPassword); + Q_INVOKABLE void startAudioMeter(bool async); + Q_INVOKABLE void stopAudioMeter(bool async); + Q_INVOKABLE void startPreviewing(bool force); + Q_INVOKABLE void stopPreviewing(); + Q_INVOKABLE bool hasVideoCall(); + Q_INVOKABLE bool isPreviewing(); + Q_INVOKABLE void setCurrAccDisplayName(QString text); + Q_INVOKABLE void setSelectedAccountId(QString accountId = {}); + Q_INVOKABLE void setSelectedConvId(QString accountId = {}); + + /* + * lrc model instances getter + */ + Q_INVOKABLE lrc::api::NewAccountModel *accoundModel(); + Q_INVOKABLE lrc::api::AVModel *avModel(); + Q_INVOKABLE lrc::api::DataTransferModel *dataTransferModel(); + + Q_INVOKABLE RenderManager *getRenderManager(); +signals: + + /* + * Trigger other components to reconnect account related signals. + */ + void accountSignalsReconnect(const QString &accountId); + void accountStatusChanged(); + void updateConversationForAddedContact(); + /* + * send report failure to QML to make it show the right UI state . + */ + void reportFailure(); + void accountAdded(bool showBackUp, int index); + +private: + void initQmlObject() override final; + void setSelectedAccount(const QString &accountId, int index); + void backToWelcomePage(int index); + void deselectConversation(); + + /* + * Make account signal connections. + */ + void connectAccount(const QString &accountId); + /* + * Implement what to do when creat accout fails. + */ + void connectFailure(); + + QMetaObject::Connection accountStatusChangedConnection_; + QMetaObject::Connection contactAddedConnection_; + QMetaObject::Connection addedToConferenceConnection_; +}; +#if QT_VERSION >= QT_VERSION_CHECK(5, 8, 0) +Q_DECLARE_METATYPE(AccountAdapter *) +#endif diff --git a/src/accountlistmodel.cpp b/src/accountlistmodel.cpp new file mode 100644 index 00000000..9b3eed41 --- /dev/null +++ b/src/accountlistmodel.cpp @@ -0,0 +1,139 @@ +/* + * Copyright (C) 2019-2020 by Savoir-faire Linux + * Author: Andreas Traczyk + * Author: Mingrui Zhang + * + * 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 . + */ + +#include "accountlistmodel.h" + +#include + +#include "globalinstances.h" + +#include "lrcinstance.h" +#include "pixbufmanipulator.h" +#include "utils.h" + +AccountListModel::AccountListModel(QObject *parent) + : QAbstractListModel(parent) +{} + +AccountListModel::~AccountListModel() {} + +int +AccountListModel::rowCount(const QModelIndex &parent) const +{ + if (!parent.isValid()) { + /* + * Count. + */ + return LRCInstance::accountModel().getAccountList().size(); + } + /* + * A valid QModelIndex returns 0 as no entry has sub-elements. + */ + return 0; +} + +int +AccountListModel::columnCount(const QModelIndex &parent) const +{ + Q_UNUSED(parent); + /* + * Only need one column. + */ + return 1; +} + +QVariant +AccountListModel::data(const QModelIndex &index, int role) const +{ + auto accountList = LRCInstance::accountModel().getAccountList(); + if (!index.isValid() || accountList.size() <= index.row()) { + return QVariant(); + } + + auto &accountInfo = LRCInstance::accountModel().getAccountInfo(accountList.at(index.row())); + + switch (role) { + case Role::Alias: + return QVariant(Utils::bestNameForAccount(accountInfo)); + case Role::Username: + return QVariant(Utils::secondBestNameForAccount(accountInfo)); + case Role::Type: + return QVariant( + Utils::toUnderlyingValue(accountInfo.profileInfo.type)); + case Role::Status: + return QVariant(Utils::toUnderlyingValue(accountInfo.status)); + case Role::Picture: + return QString::fromLatin1( + Utils::QImageToByteArray(Utils::accountPhoto(accountInfo)).toBase64().data()); + case Role::ID: + return QVariant(accountInfo.id); + } + return QVariant(); +} + +QHash +AccountListModel::roleNames() const +{ + QHash roles; + roles[Alias] = "Alias"; + roles[Username] = "Username"; + roles[Picture] = "Picture"; + roles[Type] = "Type"; + roles[Status] = "Status"; + roles[ID] = "ID"; + return roles; +} + +QModelIndex +AccountListModel::index(int row, int column, const QModelIndex &parent) const +{ + Q_UNUSED(parent); + if (column != 0) { + return QModelIndex(); + } + + if (row >= 0 && row < rowCount()) { + return createIndex(row, column); + } + return QModelIndex(); +} + +QModelIndex +AccountListModel::parent(const QModelIndex &child) const +{ + Q_UNUSED(child); + return QModelIndex(); +} + +Qt::ItemFlags +AccountListModel::flags(const QModelIndex &index) const +{ + auto flags = QAbstractItemModel::flags(index) | Qt::ItemNeverHasChildren | Qt::ItemIsSelectable; + if (!index.isValid()) { + return QAbstractItemModel::flags(index); + } + return flags; +} + +void +AccountListModel::reset() +{ + beginResetModel(); + endResetModel(); +} diff --git a/src/accountlistmodel.h b/src/accountlistmodel.h new file mode 100644 index 00000000..134a31e2 --- /dev/null +++ b/src/accountlistmodel.h @@ -0,0 +1,56 @@ +/* + * Copyright (C) 2019-2020 by Savoir-faire Linux + * Author: Andreas Traczyk + * Author: Mingrui Zhang + * + * 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 . + */ + +#pragma once + +#include + +#include "api/account.h" +#include "api/contact.h" +#include "api/conversation.h" + +class AccountListModel : public QAbstractListModel +{ + Q_OBJECT + +public: + enum Role { Alias = Qt::UserRole + 1, Username, Picture, Type, Status, ID }; + + explicit AccountListModel(QObject *parent = 0); + ~AccountListModel(); + + /* + * QAbstractListModel override. + */ + int rowCount(const QModelIndex &parent = QModelIndex()) const override; + int columnCount(const QModelIndex &parent) const override; + QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override; + /* + * Override role name as access point in qml. + */ + QHash roleNames() const override; + QModelIndex index(int row, int column = 0, const QModelIndex &parent = QModelIndex()) const; + QModelIndex parent(const QModelIndex &child) const; + Qt::ItemFlags flags(const QModelIndex &index) const; + + /* + * This function is to reset the model when there's new account added. + */ + Q_INVOKABLE void reset(); +}; diff --git a/src/accountstomigratelistmodel.cpp b/src/accountstomigratelistmodel.cpp new file mode 100644 index 00000000..8123eec1 --- /dev/null +++ b/src/accountstomigratelistmodel.cpp @@ -0,0 +1,151 @@ +/* + * Copyright (C) 2019-2020 by Savoir-faire Linux + * Author: Yang Wang + * + * 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 . + */ + +#include "accountstomigratelistmodel.h" + +AccountsToMigrateListModel::AccountsToMigrateListModel(QObject *parent) + : QAbstractListModel(parent) +{} + +AccountsToMigrateListModel::~AccountsToMigrateListModel() {} + +int +AccountsToMigrateListModel::rowCount(const QModelIndex &parent) const +{ + if (!parent.isValid()) { + /* + * Count. + */ + auto accountList = LRCInstance::accountModel().getAccountList(); + + int countAccountToMigrate = 0; + + for (const QString &i : accountList) { + auto accountStatus = LRCInstance::accountModel().getAccountInfo(i).status; + if (accountStatus == lrc::api::account::Status::ERROR_NEED_MIGRATION) { + countAccountToMigrate++; + } + } + + return countAccountToMigrate; + } + /* + * A valid QModelIndex returns 0 as no entry has sub-elements. + */ + return 0; +} + +int +AccountsToMigrateListModel::columnCount(const QModelIndex &parent) const +{ + Q_UNUSED(parent); + /* + * Only need one column. + */ + return 1; +} + +QVariant +AccountsToMigrateListModel::data(const QModelIndex &index, int role) const +{ + auto accountList = LRCInstance::accountModel().getAccountList(); + if (!index.isValid() || accountList.size() <= index.row()) { + return QVariant(); + } + + QList accountToMigrateList; + + for (QString i : accountList) { + auto accountStatus = LRCInstance::accountModel().getAccountInfo(i).status; + if (accountStatus == lrc::api::account::Status::ERROR_NEED_MIGRATION) { + accountToMigrateList.append(i); + } + } + + QString accountId = accountToMigrateList.at(index.row()); + + auto &avatarInfo = LRCInstance::accountModel().getAccountInfo(accountId); + + switch (role) { + case Role::Account_ID: + return QVariant(accountId); + case Role::ManagerUsername: + return QVariant(avatarInfo.confProperties.managerUsername); + case Role::ManagerUri: + return QVariant(avatarInfo.confProperties.managerUri); + case Role::Username: + return QVariant(avatarInfo.confProperties.username); + case Role::Alias: + return QVariant(LRCInstance::accountModel().getAccountInfo(accountId).profileInfo.alias); + case Role::Picture: + return QString::fromLatin1( + Utils::QImageToByteArray(Utils::accountPhoto(avatarInfo)).toBase64().data()); + } + return QVariant(); +} + +QHash +AccountsToMigrateListModel::roleNames() const +{ + QHash roles; + roles[Account_ID] = "Account_ID"; + roles[ManagerUsername] = "ManagerUsername"; + roles[ManagerUri] = "ManagerUri"; + roles[Username] = "Username"; + roles[Alias] = "Alias"; + roles[Picture] = "Picture"; + return roles; +} + +QModelIndex +AccountsToMigrateListModel::index(int row, int column, const QModelIndex &parent) const +{ + Q_UNUSED(parent); + if (column != 0) { + return QModelIndex(); + } + + if (row >= 0 && row < rowCount()) { + return createIndex(row, column); + } + return QModelIndex(); +} + +QModelIndex +AccountsToMigrateListModel::parent(const QModelIndex &child) const +{ + Q_UNUSED(child); + return QModelIndex(); +} + +Qt::ItemFlags +AccountsToMigrateListModel::flags(const QModelIndex &index) const +{ + auto flags = QAbstractItemModel::flags(index) | Qt::ItemNeverHasChildren | Qt::ItemIsSelectable; + if (!index.isValid()) { + return QAbstractItemModel::flags(index); + } + return flags; +} + +void +AccountsToMigrateListModel::reset() +{ + beginResetModel(); + endResetModel(); +} diff --git a/src/accountstomigratelistmodel.h b/src/accountstomigratelistmodel.h new file mode 100644 index 00000000..b865d00b --- /dev/null +++ b/src/accountstomigratelistmodel.h @@ -0,0 +1,65 @@ +/* + * Copyright (C) 2019-2020 by Savoir-faire Linux + * Author: Yang Wang + * + * 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 . + */ + +#pragma once + +#include + +#include "api/account.h" +#include "api/contact.h" +#include "api/conversation.h" +#include "api/newdevicemodel.h" + +#include "lrcinstance.h" + +class AccountsToMigrateListModel : public QAbstractListModel +{ + Q_OBJECT +public: + enum Role { + Account_ID = Qt::UserRole + 1, + ManagerUsername, + ManagerUri, + Username, + Alias, + Picture + }; + Q_ENUM(Role) + + explicit AccountsToMigrateListModel(QObject *parent = 0); + ~AccountsToMigrateListModel(); + + /* + * QAbstractListModel override. + */ + int rowCount(const QModelIndex &parent = QModelIndex()) const override; + int columnCount(const QModelIndex &parent) const override; + QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override; + /* + * Override role name as access point in qml. + */ + QHash roleNames() const override; + QModelIndex index(int row, int column = 0, const QModelIndex &parent = QModelIndex()) const; + QModelIndex parent(const QModelIndex &child) const; + Qt::ItemFlags flags(const QModelIndex &index) const; + + /* + * This function is to reset the model when there's new account added. + */ + Q_INVOKABLE void reset(); +}; diff --git a/src/audiocodeclistmodel.cpp b/src/audiocodeclistmodel.cpp new file mode 100644 index 00000000..cf097ad4 --- /dev/null +++ b/src/audiocodeclistmodel.cpp @@ -0,0 +1,108 @@ +/* + * Copyright (C) 2019-2020 by Savoir-faire Linux + * Author: Yang Wang + * + * 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 . + */ + +#include "audiocodeclistmodel.h" + +AudioCodecListModel::AudioCodecListModel(QObject *parent) + : QAbstractListModel(parent) +{} + +AudioCodecListModel::~AudioCodecListModel() {} + +int +AudioCodecListModel::rowCount(const QModelIndex &parent) const +{ + if (!parent.isValid()) { + return LRCInstance::getCurrentAccountInfo().codecModel->getAudioCodecs().size(); + } + return 0; +} + +int +AudioCodecListModel::columnCount(const QModelIndex &parent) const +{ + Q_UNUSED(parent); + /* + * Only need one column. + */ + return 1; +} + +QVariant +AudioCodecListModel::data(const QModelIndex &index, int role) const +{ + auto audioCodecList = LRCInstance::getCurrentAccountInfo().codecModel->getAudioCodecs(); + if (!index.isValid() || audioCodecList.size() <= index.row()) { + return QVariant(); + } + + switch (role) { + case Role::AudioCodecName: + return QVariant(audioCodecList.at(index.row()).name); + case Role::IsEnabled: + return QVariant(audioCodecList.at(index.row()).enabled); + case Role::AudioCodecID: + return QVariant(audioCodecList.at(index.row()).id); + case Role::Samplerate: + return QVariant(audioCodecList.at(index.row()).samplerate); + } + return QVariant(); +} + +QHash +AudioCodecListModel::roleNames() const +{ + QHash roles; + roles[AudioCodecName] = "AudioCodecName"; + roles[IsEnabled] = "IsEnabled"; + roles[AudioCodecID] = "AudioCodecID"; + roles[Samplerate] = "Samplerate"; + return roles; +} + +QModelIndex +AudioCodecListModel::index(int row, int column, const QModelIndex &parent) const +{ + Q_UNUSED(parent); + if (column != 0) { + return QModelIndex(); + } + + if (row >= 0 && row < rowCount()) { + return createIndex(row, column); + } + return QModelIndex(); +} + +QModelIndex +AudioCodecListModel::parent(const QModelIndex &child) const +{ + Q_UNUSED(child); + return QModelIndex(); +} + +Qt::ItemFlags +AudioCodecListModel::flags(const QModelIndex &index) const +{ + auto flags = QAbstractItemModel::flags(index) | Qt::ItemNeverHasChildren | Qt::ItemIsSelectable + | Qt::ItemIsUserCheckable | Qt::ItemIsEnabled; + if (!index.isValid()) { + return QAbstractItemModel::flags(index); + } + return flags; +} diff --git a/src/audiocodeclistmodel.h b/src/audiocodeclistmodel.h new file mode 100644 index 00000000..fc58ee1a --- /dev/null +++ b/src/audiocodeclistmodel.h @@ -0,0 +1,53 @@ +/* + * Copyright (C) 2019-2020 by Savoir-faire Linux + * Author: Yang Wang + * + * 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 . + */ + +#pragma once + +#include + +#include "api/account.h" +#include "api/contact.h" +#include "api/conversation.h" +#include "api/newdevicemodel.h" + +#include "lrcinstance.h" + +class AudioCodecListModel : public QAbstractListModel +{ + Q_OBJECT +public: + enum Role { AudioCodecName = Qt::UserRole + 1, IsEnabled, AudioCodecID, Samplerate }; + Q_ENUM(Role) + + explicit AudioCodecListModel(QObject *parent = 0); + ~AudioCodecListModel(); + + /* + * QAbstractListModel override. + */ + int rowCount(const QModelIndex &parent = QModelIndex()) const override; + int columnCount(const QModelIndex &parent) const override; + QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override; + /* + * Override role name as access point in qml. + */ + QHash roleNames() const override; + QModelIndex index(int row, int column = 0, const QModelIndex &parent = QModelIndex()) const; + QModelIndex parent(const QModelIndex &child) const; + Qt::ItemFlags flags(const QModelIndex &index) const; +}; diff --git a/src/audioinputdevicemodel.cpp b/src/audioinputdevicemodel.cpp new file mode 100644 index 00000000..0687c4e4 --- /dev/null +++ b/src/audioinputdevicemodel.cpp @@ -0,0 +1,128 @@ +/* + * Copyright (C) 2019-2020 by Savoir-faire Linux + * Author: Yang Wang + * + * 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 . + */ + +#include "audioinputdevicemodel.h" + +AudioInputDeviceModel::AudioInputDeviceModel(QObject *parent) + : QAbstractListModel(parent) +{} + +AudioInputDeviceModel::~AudioInputDeviceModel() {} + +int +AudioInputDeviceModel::rowCount(const QModelIndex &parent) const +{ + if (!parent.isValid()) { + /* + * Count. + */ + return LRCInstance::avModel().getAudioInputDevices().size(); + } + /* + * A valid QModelIndex returns 0 as no entry has sub-elements. + */ + return 0; +} + +int +AudioInputDeviceModel::columnCount(const QModelIndex &parent) const +{ + Q_UNUSED(parent); + /* + * Only need one column. + */ + return 1; +} + +QVariant +AudioInputDeviceModel::data(const QModelIndex &index, int role) const +{ + auto deviceList = LRCInstance::avModel().getAudioInputDevices(); + if (!index.isValid() || deviceList.size() <= index.row()) { + return QVariant(); + } + + switch (role) { + case Role::Device_ID: + return QVariant(deviceList.at(index.row())); + case Role::ID_UTF8: + return QVariant(deviceList.at(index.row()).toUtf8()); + } + return QVariant(); +} + +QHash +AudioInputDeviceModel::roleNames() const +{ + QHash roles; + roles[Device_ID] = "Device_ID"; + roles[ID_UTF8] = "ID_UTF8"; + return roles; +} + +QModelIndex +AudioInputDeviceModel::index(int row, int column, const QModelIndex &parent) const +{ + Q_UNUSED(parent); + if (column != 0) { + return QModelIndex(); + } + + if (row >= 0 && row < rowCount()) { + return createIndex(row, column); + } + return QModelIndex(); +} + +QModelIndex +AudioInputDeviceModel::parent(const QModelIndex &child) const +{ + Q_UNUSED(child); + return QModelIndex(); +} + +Qt::ItemFlags +AudioInputDeviceModel::flags(const QModelIndex &index) const +{ + auto flags = QAbstractItemModel::flags(index) | Qt::ItemNeverHasChildren | Qt::ItemIsSelectable; + if (!index.isValid()) { + return QAbstractItemModel::flags(index); + } + return flags; +} + +void +AudioInputDeviceModel::reset() +{ + beginResetModel(); + endResetModel(); +} + +int +AudioInputDeviceModel::getCurrentSettingIndex() +{ + QString currentId = LRCInstance::avModel().getInputDevice(); + auto resultList = match(index(0, 0), Device_ID, QVariant(currentId)); + + int resultRowIndex = 0; + if (resultList.size() > 0) { + resultRowIndex = resultList[0].row(); + } + + return resultRowIndex; +} diff --git a/src/audioinputdevicemodel.h b/src/audioinputdevicemodel.h new file mode 100644 index 00000000..03836bed --- /dev/null +++ b/src/audioinputdevicemodel.h @@ -0,0 +1,62 @@ +/* + * Copyright (C) 2019-2020 by Savoir-faire Linux + * Author: Yang Wang + * + * 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 . + */ + +#pragma once + +#include + +#include "api/account.h" +#include "api/contact.h" +#include "api/conversation.h" +#include "api/newdevicemodel.h" + +#include "lrcinstance.h" + +class AudioInputDeviceModel : public QAbstractListModel +{ + Q_OBJECT +public: + enum Role { Device_ID = Qt::UserRole + 1, ID_UTF8 }; + Q_ENUM(Role) + + explicit AudioInputDeviceModel(QObject *parent = 0); + ~AudioInputDeviceModel(); + + /* + * QAbstractListModel override. + */ + int rowCount(const QModelIndex &parent = QModelIndex()) const override; + int columnCount(const QModelIndex &parent) const override; + QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override; + /* + * Override role name as access point in qml. + */ + QHash roleNames() const override; + QModelIndex index(int row, int column = 0, const QModelIndex &parent = QModelIndex()) const; + QModelIndex parent(const QModelIndex &child) const; + Qt::ItemFlags flags(const QModelIndex &index) const; + + /* + * This function is to reset the model when there's new account added. + */ + Q_INVOKABLE void reset(); + /* + * This function is to get the current device id in the demon. + */ + Q_INVOKABLE int getCurrentSettingIndex(); +}; diff --git a/src/audiomanagerlistmodel.cpp b/src/audiomanagerlistmodel.cpp new file mode 100644 index 00000000..a28480bf --- /dev/null +++ b/src/audiomanagerlistmodel.cpp @@ -0,0 +1,128 @@ +/* + * Copyright (C) 2019-2020 by Savoir-faire Linux + * Author: Yang Wang + * + * 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 . + */ + +#include "audiomanagerlistmodel.h" + +AudioManagerListModel::AudioManagerListModel(QObject *parent) + : QAbstractListModel(parent) +{} + +AudioManagerListModel::~AudioManagerListModel() {} + +int +AudioManagerListModel::rowCount(const QModelIndex &parent) const +{ + if (!parent.isValid()) { + /* + * Count. + */ + return LRCInstance::avModel().getSupportedAudioManagers().size(); + } + /* + * A valid QModelIndex returns 0 as no entry has sub-elements. + */ + return 0; +} + +int +AudioManagerListModel::columnCount(const QModelIndex &parent) const +{ + Q_UNUSED(parent); + /* + * Only need one column. + */ + return 1; +} + +QVariant +AudioManagerListModel::data(const QModelIndex &index, int role) const +{ + auto managerList = LRCInstance::avModel().getSupportedAudioManagers(); + if (!index.isValid() || managerList.size() <= index.row()) { + return QVariant(); + } + + switch (role) { + case Role::AudioManagerID: + return QVariant(managerList.at(index.row())); + case Role::ID_UTF8: + return QVariant(managerList.at(index.row()).toUtf8()); + } + return QVariant(); +} + +QHash +AudioManagerListModel::roleNames() const +{ + QHash roles; + roles[AudioManagerID] = "AudioManagerID"; + roles[ID_UTF8] = "ID_UTF8"; + return roles; +} + +QModelIndex +AudioManagerListModel::index(int row, int column, const QModelIndex &parent) const +{ + Q_UNUSED(parent); + if (column != 0) { + return QModelIndex(); + } + + if (row >= 0 && row < rowCount()) { + return createIndex(row, column); + } + return QModelIndex(); +} + +QModelIndex +AudioManagerListModel::parent(const QModelIndex &child) const +{ + Q_UNUSED(child); + return QModelIndex(); +} + +Qt::ItemFlags +AudioManagerListModel::flags(const QModelIndex &index) const +{ + auto flags = QAbstractItemModel::flags(index) | Qt::ItemNeverHasChildren | Qt::ItemIsSelectable; + if (!index.isValid()) { + return QAbstractItemModel::flags(index); + } + return flags; +} + +void +AudioManagerListModel::reset() +{ + beginResetModel(); + endResetModel(); +} + +int +AudioManagerListModel::getCurrentSettingIndex() +{ + QString currentId = LRCInstance::avModel().getAudioManager(); + auto resultList = match(index(0, 0), AudioManagerID, QVariant(currentId)); + + int resultRowIndex = 0; + if (resultList.size() > 0) { + resultRowIndex = resultList[0].row(); + } + + return resultRowIndex; +} diff --git a/src/audiomanagerlistmodel.h b/src/audiomanagerlistmodel.h new file mode 100644 index 00000000..56f0b3ba --- /dev/null +++ b/src/audiomanagerlistmodel.h @@ -0,0 +1,62 @@ +/* + * Copyright (C) 2019-2020 by Savoir-faire Linux + * Author: Yang Wang + * + * 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 . + */ + +#pragma once + +#include + +#include "api/account.h" +#include "api/contact.h" +#include "api/conversation.h" +#include "api/newdevicemodel.h" + +#include "lrcinstance.h" + +class AudioManagerListModel : public QAbstractListModel +{ + Q_OBJECT +public: + enum Role { AudioManagerID = Qt::UserRole + 1, ID_UTF8 }; + Q_ENUM(Role) + + explicit AudioManagerListModel(QObject *parent = 0); + ~AudioManagerListModel(); + + /* + * QAbstractListModel override. + */ + int rowCount(const QModelIndex &parent = QModelIndex()) const override; + int columnCount(const QModelIndex &parent) const override; + QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override; + /* + * Override role name as access point in qml. + */ + QHash roleNames() const override; + QModelIndex index(int row, int column = 0, const QModelIndex &parent = QModelIndex()) const; + QModelIndex parent(const QModelIndex &child) const; + Qt::ItemFlags flags(const QModelIndex &index) const; + + /* + * This function is to reset the model when there's new account added. + */ + Q_INVOKABLE void reset(); + /* + * This function is to get the current device id in the demon. + */ + Q_INVOKABLE int getCurrentSettingIndex(); +}; diff --git a/src/audiooutputdevicemodel.cpp b/src/audiooutputdevicemodel.cpp new file mode 100644 index 00000000..733cc6d7 --- /dev/null +++ b/src/audiooutputdevicemodel.cpp @@ -0,0 +1,142 @@ +/* + * Copyright (C) 2019-2020 by Savoir-faire Linux + * Author: Yang Wang + * + * 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 . + */ + +#include "audiooutputdevicemodel.h" + +AudioOutputDeviceModel::AudioOutputDeviceModel(QObject *parent) + : QAbstractListModel(parent) +{} + +AudioOutputDeviceModel::~AudioOutputDeviceModel() {} + +int +AudioOutputDeviceModel::rowCount(const QModelIndex &parent) const +{ + if (!parent.isValid()) { + /* + * Count. + */ + return LRCInstance::avModel().getAudioOutputDevices().size(); + } + /* + * A valid QModelIndex returns 0 as no entry has sub-elements. + */ + return 0; +} + +int +AudioOutputDeviceModel::columnCount(const QModelIndex &parent) const +{ + Q_UNUSED(parent); + /* + * Only need one column. + */ + return 1; +} + +QVariant +AudioOutputDeviceModel::data(const QModelIndex &index, int role) const +{ + auto deviceList = LRCInstance::avModel().getAudioOutputDevices(); + if (!index.isValid() || deviceList.size() <= index.row()) { + return QVariant(); + } + + switch (role) { + case Role::Device_ID: + return QVariant(deviceList.at(index.row())); + case Role::ID_UTF8: + return QVariant(deviceList.at(index.row()).toUtf8()); + } + return QVariant(); +} + +QHash +AudioOutputDeviceModel::roleNames() const +{ + QHash roles; + roles[Device_ID] = "Device_ID"; + roles[ID_UTF8] = "ID_UTF8"; + return roles; +} + +QModelIndex +AudioOutputDeviceModel::index(int row, int column, const QModelIndex &parent) const +{ + Q_UNUSED(parent); + if (column != 0) { + return QModelIndex(); + } + + if (row >= 0 && row < rowCount()) { + return createIndex(row, column); + } + return QModelIndex(); +} + +QModelIndex +AudioOutputDeviceModel::parent(const QModelIndex &child) const +{ + Q_UNUSED(child); + return QModelIndex(); +} + +Qt::ItemFlags +AudioOutputDeviceModel::flags(const QModelIndex &index) const +{ + auto flags = QAbstractItemModel::flags(index) | Qt::ItemNeverHasChildren | Qt::ItemIsSelectable; + if (!index.isValid()) { + return QAbstractItemModel::flags(index); + } + return flags; +} + +void +AudioOutputDeviceModel::reset() +{ + beginResetModel(); + endResetModel(); +} + +int +AudioOutputDeviceModel::getCurrentSettingIndex() +{ + QString currentId = LRCInstance::avModel().getOutputDevice(); + auto resultList = match(index(0, 0), Device_ID, QVariant(currentId)); + + int resultRowIndex = 0; + if (resultList.size() > 0) { + resultRowIndex = resultList[0].row(); + } + + return resultRowIndex; +} + +int +AudioOutputDeviceModel::getCurrentRingtoneDeviceIndex() +{ + QString currentId = LRCInstance::avModel().getRingtoneDevice(); + auto resultList = match(index(0, 0), Device_ID, QVariant(currentId)); + + int resultRowIndex = 0; + if (resultList.size() > 0) { + resultRowIndex = resultList[0].row(); + } + + return resultRowIndex; +} diff --git a/src/audiooutputdevicemodel.h b/src/audiooutputdevicemodel.h new file mode 100644 index 00000000..e0148a1e --- /dev/null +++ b/src/audiooutputdevicemodel.h @@ -0,0 +1,67 @@ +/* + * Copyright (C) 2019-2020 by Savoir-faire Linux + * Author: Yang Wang + * + * 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 . + */ + +#pragma once + +#include + +#include "api/account.h" +#include "api/contact.h" +#include "api/conversation.h" +#include "api/newdevicemodel.h" + +#include "lrcinstance.h" + +class AudioOutputDeviceModel : public QAbstractListModel +{ + Q_OBJECT +public: +public: + enum Role { Device_ID = Qt::UserRole + 1, ID_UTF8 }; + Q_ENUM(Role) + + explicit AudioOutputDeviceModel(QObject *parent = 0); + ~AudioOutputDeviceModel(); + + /* + * QAbstractListModel override. + */ + int rowCount(const QModelIndex &parent = QModelIndex()) const override; + int columnCount(const QModelIndex &parent) const override; + QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override; + /* + * Override role name as access point in qml. + */ + QHash roleNames() const override; + QModelIndex index(int row, int column = 0, const QModelIndex &parent = QModelIndex()) const; + QModelIndex parent(const QModelIndex &child) const; + Qt::ItemFlags flags(const QModelIndex &index) const; + + /* + * This function is to reset the model when there's new account added. + */ + Q_INVOKABLE void reset(); + /* + * This function is to get the current device id in the demon. + */ + Q_INVOKABLE int getCurrentSettingIndex(); + /* + * This function is to get the current ringtone device id in the demon. + */ + Q_INVOKABLE int getCurrentRingtoneDeviceIndex(); +}; diff --git a/src/avadapter.cpp b/src/avadapter.cpp new file mode 100644 index 00000000..406e2085 --- /dev/null +++ b/src/avadapter.cpp @@ -0,0 +1,132 @@ +/* + * Copyright (C) 2020 by Savoir-faire Linux + * Author : Edric Ladent Milaret + * Author : Andreas Traczyk + * Author: Mingrui Zhang + * + * 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 . + */ + +#include "avadapter.h" + +#include "lrcinstance.h" + +#include + +AvAdapter::AvAdapter(QObject *parent) + : QmlAdapterBase(parent) +{} + +AvAdapter::~AvAdapter() {} + +void +AvAdapter::initQmlObject() +{} + +QVariantMap +AvAdapter::populateVideoDeviceContextMenuItem() +{ + auto conversation = LRCInstance::getCurrentConversation(); + auto call = LRCInstance::getCallInfoForConversation(conversation); + if (!call) { + return QVariantMap(); + } + + auto activeDevice = LRCInstance::avModel().getCurrentRenderedDevice(call->id); + + /* + * Create a list of video input devices. + */ + QVariantMap deciveContextMenuNeededInfo; + auto devices = LRCInstance::avModel().getDevices(); + for (int i = 0; i < devices.size(); i++) { + try { + auto settings = LRCInstance::avModel().getDeviceSettings(devices[i]); + deciveContextMenuNeededInfo[settings.name] = QVariant(devices[i] == activeDevice.name); + } catch (...) { + qDebug().noquote() << "Error in getting device settings"; + } + } + + /* + * Add size parameter into the map since in qml there is no way to get the size. + */ + deciveContextMenuNeededInfo["size"] = QVariant(deciveContextMenuNeededInfo.size()); + + return deciveContextMenuNeededInfo; +} + +void +AvAdapter::onVideoContextMenuDeviceItemClicked(const QString &deviceName) +{ + auto deviceId = LRCInstance::avModel().getDeviceIdFromName(deviceName); + if (deviceId.isEmpty()) { + qWarning() << "Couldn't find device: " << deviceName; + return; + } + LRCInstance::avModel().switchInputTo(deviceId); + LRCInstance::avModel().setCurrentVideoCaptureDevice(deviceId); +} + +void +AvAdapter::shareEntireScreen(int screenNumber) +{ + QScreen *screen = qApp->screens().at(screenNumber); + if (!screen) + return; + QRect rect = screen ? screen->geometry() : qApp->primaryScreen()->geometry(); + LRCInstance::avModel().setDisplay(screenNumber, rect.x(), rect.y(), rect.width(), rect.height()); +} + +const QString +AvAdapter::captureScreen(int screenNumber) +{ + QScreen *screen = qApp->screens().at(screenNumber); + if (!screen) + return QString(""); + /* + * The screen window id is always 0. + */ + auto pixmap = screen->grabWindow(0); + + QBuffer buffer; + buffer.open(QIODevice::WriteOnly); + pixmap.save(&buffer, "PNG"); + return QString::fromLatin1(buffer.data().toBase64().data()); +} + +void +AvAdapter::shareFile(const QString &filePath) +{ + LRCInstance::avModel().setInputFile(filePath); +} + +void +AvAdapter::shareScreenArea(int screenNumber, int x, int y, int width, int height) +{ + QScreen *screen = qApp->screens().at(screenNumber); + if (!screen) + return; + QRect rect = screen ? screen->geometry() : qApp->primaryScreen()->geometry(); + + /* + * Provide minimum width, height. + * Need to add screen x, y initial value to the setDisplay api call. + */ + LRCInstance::avModel().setDisplay(screenNumber, + rect.x() + x, + rect.y() + y, + width < 128 ? 128 : width, + height < 128 ? 128 : height); +} \ No newline at end of file diff --git a/src/avadapter.h b/src/avadapter.h new file mode 100644 index 00000000..1c300e88 --- /dev/null +++ b/src/avadapter.h @@ -0,0 +1,67 @@ +/* + * Copyright (C) 2020 by Savoir-faire Linux + * Author: Mingrui Zhang + * + * 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 . + */ + +#pragma once + +#include "qmladapterbase.h" + +#include +#include +#include + +class AvAdapter : public QmlAdapterBase +{ + Q_OBJECT + +public: + explicit AvAdapter(QObject *parent = nullptr); + ~AvAdapter(); + + /* + * Return needed info for populating video device context menu item. + */ + Q_INVOKABLE QVariantMap populateVideoDeviceContextMenuItem(); + + /* + * Preview video input switching. + */ + Q_INVOKABLE void onVideoContextMenuDeviceItemClicked(const QString &deviceName); + + /* + * Share the screen specificed by screen number. + */ + Q_INVOKABLE void shareEntireScreen(int screenNumber); + + /* + * Take snap shot of the screen by returning base64 image string. + */ + Q_INVOKABLE const QString captureScreen(int screenNumber); + + /* + * Share a media file. + */ + Q_INVOKABLE void shareFile(const QString &filePath); + + /* + * Select screen area to display. + */ + Q_INVOKABLE void shareScreenArea(int screenNumber, int x, int y, int width, int height); + +private: + void initQmlObject() override; +}; diff --git a/src/bannedlistmodel.cpp b/src/bannedlistmodel.cpp new file mode 100644 index 00000000..79fecd43 --- /dev/null +++ b/src/bannedlistmodel.cpp @@ -0,0 +1,120 @@ +/* + * Copyright (C) 2019-2020 by Savoir-faire Linux + * Author: Isa Nanic + * Author: Yang Wang + * + * 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 . + */ + +#include "bannedlistmodel.h" +#include "lrcinstance.h" + +BannedListModel::BannedListModel(QObject *parent) + : QAbstractListModel(parent) +{} + +BannedListModel::~BannedListModel() {} + +int +BannedListModel::rowCount(const QModelIndex &parent) const +{ + if (!parent.isValid()) { + return LRCInstance::getCurrentAccountInfo().contactModel->getBannedContacts().size(); + } + return 0; +} + +int +BannedListModel::columnCount(const QModelIndex &parent) const +{ + Q_UNUSED(parent); + /* + * Only need one column. + */ + return 1; +} + +QVariant +BannedListModel::data(const QModelIndex &index, int role) const +{ + auto contactList = LRCInstance::getCurrentAccountInfo().contactModel->getBannedContacts(); + if (!index.isValid() || contactList.size() <= index.row()) { + return QVariant(); + } + + auto contactInfo = LRCInstance::getCurrentAccountInfo().contactModel->getContact( + contactList.at(index.row())); + + switch (role) { + case Role::ContactName: + return QVariant(contactInfo.registeredName); + case Role::ContactID: + return QVariant(contactInfo.profileInfo.uri); + case Role::ContactPicture: + QImage avatarImage = Utils::fallbackAvatar(QSize(48, 48), + contactInfo.profileInfo.uri, + contactInfo.registeredName); + + return QString::fromLatin1(Utils::QImageToByteArray(avatarImage).toBase64().data()); + } + return QVariant(); +} + +QHash +BannedListModel::roleNames() const +{ + QHash roles; + roles[ContactName] = "ContactName"; + roles[ContactID] = "ContactID"; + roles[ContactPicture] = "ContactPicture"; + return roles; +} + +QModelIndex +BannedListModel::index(int row, int column, const QModelIndex &parent) const +{ + Q_UNUSED(parent); + if (column != 0) { + return QModelIndex(); + } + + if (row >= 0 && row < rowCount()) { + return createIndex(row, column); + } + return QModelIndex(); +} + +QModelIndex +BannedListModel::parent(const QModelIndex &child) const +{ + Q_UNUSED(child); + return QModelIndex(); +} + +Qt::ItemFlags +BannedListModel::flags(const QModelIndex &index) const +{ + auto flags = QAbstractItemModel::flags(index) | Qt::ItemNeverHasChildren | Qt::ItemIsSelectable; + if (!index.isValid()) { + return QAbstractItemModel::flags(index); + } + return flags; +} + +void +BannedListModel::reset() +{ + beginResetModel(); + endResetModel(); +} diff --git a/src/bannedlistmodel.h b/src/bannedlistmodel.h new file mode 100644 index 00000000..8dbb7a0f --- /dev/null +++ b/src/bannedlistmodel.h @@ -0,0 +1,54 @@ +/* + * Copyright (C) 2019-2020 by Savoir-faire Linux + * Author: Isa Nanic + * Author: Yang Wang + * + * 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 . + */ + +#pragma once + +#include + +class BannedListModel : public QAbstractListModel +{ + Q_OBJECT + BannedListModel(const BannedListModel &cpy); + +public: + enum Role { ContactName = Qt::UserRole + 1, ContactID, ContactPicture }; + Q_ENUM(Role) + + explicit BannedListModel(QObject *parent = nullptr); + ~BannedListModel(); + + /* + * QAbstractListModel override. + */ + int rowCount(const QModelIndex &parent = QModelIndex()) const override; + int columnCount(const QModelIndex &parent) const override; + QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override; + /* + * Override role name as access point in qml. + */ + QHash roleNames() const override; + QModelIndex index(int row, int column = 0, const QModelIndex &parent = QModelIndex()) const; + QModelIndex parent(const QModelIndex &child) const; + Qt::ItemFlags flags(const QModelIndex &index) const; + + /* + * This function is to reset the model when there's new account added. + */ + Q_INVOKABLE void reset(); +}; diff --git a/src/calladapter.cpp b/src/calladapter.cpp new file mode 100644 index 00000000..c1b32402 --- /dev/null +++ b/src/calladapter.cpp @@ -0,0 +1,444 @@ +/* + * Copyright (C) 2020 by Savoir-faire Linux + * Author: Edric Ladent Milaret + * Author: Anthony Lonard + * Author: Olivier Soldano + * Author: Andreas Traczyk + * Author: Isa Nanic + * Author: Mingrui Zhang + * + * 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 . + */ + +#include "calladapter.h" + +#include "globalsystemtray.h" +#include "utils.h" + +CallAdapter::CallAdapter(QObject *parent) + : QmlAdapterBase(parent) + , oneSecondTimer_(new QTimer(this)) +{} + +CallAdapter::~CallAdapter() {} + +void +CallAdapter::initQmlObject() +{ + connectCallStatusChanged(LRCInstance::getCurrAccId()); + + connect(&LRCInstance::behaviorController(), + &BehaviorController::showIncomingCallView, + this, + &CallAdapter::slotShowIncomingCallView); + connect(&LRCInstance::behaviorController(), + &BehaviorController::showCallView, + this, + &CallAdapter::slotShowCallView); +} + +void +CallAdapter::placeAudioOnlyCall() +{ + auto convInfo = LRCInstance::getCurrentConversation(); + if (!convInfo.uid.isEmpty()) { + LRCInstance::getCurrentConversationModel()->placeAudioOnlyCall(convInfo.uid); + } +} + +void +CallAdapter::placeCall() +{ + auto convInfo = LRCInstance::getCurrentConversation(); + if (!convInfo.uid.isEmpty()) { + LRCInstance::getCurrentConversationModel()->placeCall(convInfo.uid); + } +} + +void +CallAdapter::hangUpACall(const QString &accountId, const QString &convUid) +{ + auto convInfo = LRCInstance::getConversationFromConvUid(convUid, accountId); + if (!convInfo.uid.isEmpty()) { + LRCInstance::getAccountInfo(accountId).callModel->hangUp(convInfo.callId); + } +} + +void +CallAdapter::refuseACall(const QString &accountId, const QString &convUid) +{ + auto convInfo = LRCInstance::getConversationFromConvUid(convUid, accountId); + if (!convInfo.uid.isEmpty()) { + LRCInstance::getAccountInfo(accountId).callModel->refuse(convInfo.callId); + } +} + +void +CallAdapter::acceptACall(const QString &accountId, const QString &convUid) +{ + emit incomingCallNeedToSetupMainView(accountId, convUid); + auto convInfo = LRCInstance::getConversationFromConvUid(convUid, accountId); + if (!convInfo.uid.isEmpty()) { + LRCInstance::getAccountInfo(accountId).callModel->accept(convInfo.callId); + auto &accInfo = LRCInstance::getAccountInfo(convInfo.accountId); + accInfo.callModel->setCurrentCall(convInfo.callId); + } +} + +void +CallAdapter::slotShowIncomingCallView(const QString &accountId, const conversation::Info &convInfo) +{ + auto callModel = LRCInstance::getCurrentCallModel(); + + if (!callModel->hasCall(convInfo.callId)) { + /* + * Connection to close potential incoming call page when it is not current account. + */ + auto &accInfo = LRCInstance::accountModel().getAccountInfo(accountId); + + QObject::disconnect(closeIncomingCallPageConnection_); + + closeIncomingCallPageConnection_ + = QObject::connect(accInfo.callModel.get(), + &lrc::api::NewCallModel::callStatusChanged, + [this, accountId, uid = convInfo.uid](const QString &callId) { + auto &accInfo = LRCInstance::accountModel().getAccountInfo( + accountId); + auto &callModel = accInfo.callModel; + auto call = callModel->getCall(callId); + + switch (call.status) { + case lrc::api::call::Status::INVALID: + case lrc::api::call::Status::INACTIVE: + case lrc::api::call::Status::ENDED: + case lrc::api::call::Status::PEER_BUSY: + case lrc::api::call::Status::TIMEOUT: + case lrc::api::call::Status::TERMINATING: { + if (!uid.isEmpty()) + emit closePotentialIncomingCallPageWindow(accountId, uid); + break; + } + default: + break; + } + + emit updateConversationSmartList(); + QObject::disconnect(closeIncomingCallPageConnection_); + }); + /* + * Show incoming call page only. + */ + emit showIncomingCallPage(accountId, convInfo.uid); + return; + } + + auto call = callModel->getCall(convInfo.callId); + auto isCallSelected = LRCInstance::getCurrentConvUid() == convInfo.uid; + + if (call.isOutgoing) { + if (isCallSelected) { + emit showOutgoingCallPage(accountId, convInfo.uid); + emit showCallStack(accountId, convInfo.uid); + } + } else { + auto selectedAccountId = LRCInstance::getCurrentAccountInfo().id; + auto accountProperties = LRCInstance::accountModel().getAccountConfig(selectedAccountId); + if (accountProperties.autoAnswer) { + /* + * TODO: Auto answer + */ + } else { + emit showIncomingCallPage(accountId, convInfo.uid); + } + } + + emit callStatusChanged(lrc::api::call::to_string(call.status), accountId, convInfo.uid); + + emit updateConversationSmartList(); +} + +void +CallAdapter::slotShowCallView(const QString &accountId, const lrc::api::conversation::Info &convInfo) +{ + updateCall(convInfo.uid, accountId); +} + +void +CallAdapter::updateCall(const QString &convUid, const QString &accountId, bool forceCallOnly) +{ + accountId_ = accountId.isEmpty() ? accountId_ : accountId; + convUid_ = convUid.isEmpty() ? convUid_ : convUid; + + auto convInfo = LRCInstance::getConversationFromConvUid(convUid_, accountId_); + if (convInfo.uid.isEmpty()) { + return; + } + + auto call = LRCInstance::getCallInfoForConversation(convInfo, forceCallOnly); + if (!call) { + return; + } + + if (call->isAudioOnly) { + emit showAudioCallPage(accountId_, convUid_); + } else { + emit showVideoCallPage(accountId_, convUid_, call->id); + } + + updateCallOverlay(convInfo); + + /* + * Preview. + */ + emit previewVisibilityNeedToChange(shouldShowPreview(forceCallOnly)); + + emit showCallStack(accountId_, convUid_); +} + +bool +CallAdapter::shouldShowPreview(bool force) +{ + bool shouldShowPreview{false}; + auto convInfo = LRCInstance::getConversationFromConvUid(convUid_, accountId_); + if (convInfo.uid.isEmpty()) { + return shouldShowPreview; + } + auto call = LRCInstance::getCallInfoForConversation(convInfo, force); + if (call) { + shouldShowPreview = !call->isAudioOnly && !(call->status == lrc::api::call::Status::PAUSED) + && !call->videoMuted && call->type != lrc::api::call::Type::CONFERENCE; + } + return shouldShowPreview; +} + +void +CallAdapter::connectCallStatusChanged(const QString &accountId) +{ + auto &accInfo = LRCInstance::accountModel().getAccountInfo(accountId); + + QObject::disconnect(callStatusChangedConnection_); + + callStatusChangedConnection_ = QObject::connect( + accInfo.callModel.get(), + &lrc::api::NewCallModel::callStatusChanged, + [this, accountId](const QString &callId) { + auto &accInfo = LRCInstance::accountModel().getAccountInfo(accountId); + auto &callModel = accInfo.callModel; + auto call = callModel->getCall(callId); + + /* + * Change status label text. + */ + auto convInfo = LRCInstance::getConversationFromCallId(callId); + if (!convInfo.uid.isEmpty()) { + emit callStatusChanged(lrc::api::call::to_string(call.status), + accountId, + convInfo.uid); + } + + switch (call.status) { + case lrc::api::call::Status::INVALID: + case lrc::api::call::Status::INACTIVE: + case lrc::api::call::Status::ENDED: + case lrc::api::call::Status::PEER_BUSY: + case lrc::api::call::Status::TIMEOUT: + case lrc::api::call::Status::TERMINATING: { + LRCInstance::renderer()->removeDistantRenderer(callId); + if (convInfo.uid.isEmpty()) { + break; + } + /* + * If it's a conference, change the smartlist index + * to the next remaining participant. + */ + bool forceCallOnly{false}; + if (!convInfo.confId.isEmpty()) { + auto callList = LRCInstance::getAPI().getConferenceSubcalls(convInfo.confId); + if (callList.empty()) { + auto lastConferencee = LRCInstance::instance().popLastConferencee( + convInfo.confId); + callList.append(lastConferencee); + forceCallOnly = true; + } + for (const auto &callId : callList) { + if (!callModel->hasCall(callId)) { + continue; + } + auto otherConv = LRCInstance::getConversationFromCallId(callId); + if (!otherConv.uid.isEmpty() && otherConv.uid != convInfo.uid) { + /* + * Reset the call view corresponding accountId, uid. + */ + LRCInstance::setSelectedConvId(otherConv.uid); + showCallStack(otherConv.accountId, otherConv.uid, true); + updateCall(otherConv.uid, otherConv.accountId, forceCallOnly); + } + } + } else { + emit closeCallStack(accountId, convInfo.uid); + emit closePotentialIncomingCallPageWindow(accountId, convInfo.uid); + } + + break; + } + case lrc::api::call::Status::CONNECTED: + case lrc::api::call::Status::IN_PROGRESS: { + auto convInfo = LRCInstance::getConversationFromCallId(callId, accountId); + if (!convInfo.uid.isEmpty() && convInfo.uid == LRCInstance::getCurrentConvUid()) { + accInfo.conversationModel->selectConversation(convInfo.uid); + } + LRCInstance::renderer()->addDistantRenderer(callId); + updateCall(); + LRCInstance::getAccountInfo(accountId).callModel->setCurrentCall(callId); + break; + } + case lrc::api::call::Status::PAUSED: + updateCall(); + default: + break; + } + + emit updateConversationSmartList(); + }); +} + +/* + * For Call Overlay + */ +void +CallAdapter::updateCallOverlay(const lrc::api::conversation::Info &convInfo) +{ + setTime(accountId_, convUid_); + QObject::disconnect(oneSecondTimer_); + QObject::connect(oneSecondTimer_, &QTimer::timeout, [this] { setTime(accountId_, convUid_); }); + oneSecondTimer_->start(20); + + auto &accInfo = LRCInstance::accountModel().getAccountInfo(accountId_); + + auto call = LRCInstance::getCallInfoForConversation(convInfo); + if (!call) { + return; + } + + bool isPaused = call->status == lrc::api::call::Status::PAUSED; + bool isAudioOnly = call->isAudioOnly && !isPaused; + bool isAudioMuted = call->audioMuted && (call->status != lrc::api::call::Status::PAUSED); + bool isVideoMuted = call->videoMuted && !isPaused && !call->isAudioOnly; + bool isRecording = accInfo.callModel->isRecording(convInfo.callId); + + emit updateOverlay(isPaused, + isAudioOnly, + isAudioMuted, + isVideoMuted, + isRecording, + accInfo.profileInfo.type == lrc::api::profile::Type::SIP, + !convInfo.confId.isEmpty(), + Utils::bestNameForConversation(convInfo, + *LRCInstance::getCurrentConversationModel())); +} + +void +CallAdapter::hangUpThisCall() +{ + auto convInfo = LRCInstance::getConversationFromConvUid(convUid_, accountId_); + if (!convInfo.uid.isEmpty()) { + auto callModel = LRCInstance::getAccountInfo(accountId_).callModel.get(); + if (callModel->hasCall(convInfo.callId)) { + /* + * Store the last remaining participant of the conference, + * so we can switch the smartlist index after termination. + */ + if (!convInfo.confId.isEmpty()) { + auto callList = LRCInstance::getAPI().getConferenceSubcalls(convInfo.confId); + if (callList.size() == 2) { + for (const auto &cId : callList) { + if (cId != convInfo.callId) { + LRCInstance::instance().pushLastConferencee(convInfo.confId, cId); + } + } + } + } + callModel->hangUp(convInfo.callId); + } + } +} + +void +CallAdapter::holdThisCallToggle() +{ + auto callId = LRCInstance::getCallIdForConversationUid(convUid_, accountId_); + if (callId.isEmpty() || !LRCInstance::getCurrentCallModel()->hasCall(callId)) { + return; + } + auto callModel = LRCInstance::getCurrentCallModel(); + if (callModel->hasCall(callId)) { + callModel->togglePause(callId); + } + emit showOnHoldLabel(true); +} + +void +CallAdapter::muteThisCallToggle() +{ + auto callId = LRCInstance::getCallIdForConversationUid(convUid_, accountId_); + if (callId.isEmpty() || !LRCInstance::getCurrentCallModel()->hasCall(callId)) { + return; + } + auto callModel = LRCInstance::getCurrentCallModel(); + if (callModel->hasCall(callId)) { + callModel->toggleMedia(callId, lrc::api::NewCallModel::Media::AUDIO); + } +} + +void +CallAdapter::recordThisCallToggle() +{ + auto callId = LRCInstance::getCallIdForConversationUid(convUid_, accountId_); + if (callId.isEmpty() || !LRCInstance::getCurrentCallModel()->hasCall(callId)) { + return; + } + auto callModel = LRCInstance::getCurrentCallModel(); + if (callModel->hasCall(callId)) { + callModel->toggleAudioRecord(callId); + } +} + +void +CallAdapter::videoPauseThisCallToggle() +{ + auto callId = LRCInstance::getCallIdForConversationUid(convUid_, accountId_); + if (callId.isEmpty() || !LRCInstance::getCurrentCallModel()->hasCall(callId)) { + return; + } + auto callModel = LRCInstance::getCurrentCallModel(); + if (callModel->hasCall(callId)) { + callModel->toggleMedia(callId, lrc::api::NewCallModel::Media::VIDEO); + } + emit previewVisibilityNeedToChange(shouldShowPreview(false)); +} + +void +CallAdapter::setTime(const QString &accountId, const QString &convUid) +{ + auto callId = LRCInstance::getCallIdForConversationUid(convUid, accountId); + if (callId.isEmpty() || !LRCInstance::getCurrentCallModel()->hasCall(callId)) { + return; + } + auto callInfo = LRCInstance::getCurrentCallModel()->getCall(callId); + if (callInfo.status == lrc::api::call::Status::IN_PROGRESS + || callInfo.status == lrc::api::call::Status::PAUSED) { + auto timeString = LRCInstance::getCurrentCallModel()->getFormattedCallDuration(callId); + emit updateTimeText(timeString); + } +} \ No newline at end of file diff --git a/src/calladapter.h b/src/calladapter.h new file mode 100644 index 00000000..25768e18 --- /dev/null +++ b/src/calladapter.h @@ -0,0 +1,112 @@ +/* + * Copyright (C) 2020 by Savoir-faire Linux + * Author: Mingrui Zhang + * + * 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 . + */ + +#pragma once + +#include "lrcinstance.h" +#include "qmladapterbase.h" + +#include +#include + +class CallAdapter : public QmlAdapterBase +{ + Q_OBJECT + +public: + explicit CallAdapter(QObject *parent = nullptr); + ~CallAdapter(); + + /* + * This is needed to be public since it has to be recognized by qml. + */ + Q_INVOKABLE void initQmlObject() override; + + Q_INVOKABLE void placeAudioOnlyCall(); + Q_INVOKABLE void placeCall(); + Q_INVOKABLE void hangUpACall(const QString &accountId, const QString &convUid); + Q_INVOKABLE void refuseACall(const QString &accountId, const QString &convUid); + Q_INVOKABLE void acceptACall(const QString &accountId, const QString &convUid); + + Q_INVOKABLE void connectCallStatusChanged(const QString &accountId); + + /* + * For Call Overlay + */ + Q_INVOKABLE void hangUpThisCall(); + Q_INVOKABLE void holdThisCallToggle(); + Q_INVOKABLE void muteThisCallToggle(); + Q_INVOKABLE void recordThisCallToggle(); + Q_INVOKABLE void videoPauseThisCallToggle(); + +signals: + void showOutgoingCallPage(const QString &accountId, const QString &convUid); + void showIncomingCallPage(const QString &accountId, const QString &convUid); + void showAudioCallPage(const QString &accountId, const QString &convUid); + void showVideoCallPage(const QString &accountId, const QString &convUid, const QString &callId); + void showCallStack(const QString &accountId, const QString &convUid, bool forceReset = false); + void closeCallStack(const QString &accountId, const QString &convUid); + void closePotentialIncomingCallPageWindow(const QString &accountId, const QString &convUid); + void callStatusChanged(const QString &status, const QString &accountId, const QString &convUid); + void updateConversationSmartList(); + + void incomingCallNeedToSetupMainView(const QString &accountId, const QString &convUid); + void previewVisibilityNeedToChange(bool visible); + + /* + * For Call Overlay + */ + void updateTimeText(const QString &time); + void showOnHoldLabel(bool isPaused); + void updateOverlay(bool isPaused, + bool isAudioOnly, + bool isAudioMuted, + bool isVideoMuted, + bool isRecording, + bool isSIP, + bool isConferenceCall, + const QString &bestName); + +public slots: + void slotShowIncomingCallView(const QString &accountId, + const lrc::api::conversation::Info &convInfo); + void slotShowCallView(const QString &accountId, const lrc::api::conversation::Info &convInfo); + +private: + void updateCall(const QString &convUid = {}, + const QString &accountId = {}, + bool forceCallOnly = false); + bool shouldShowPreview(bool force); + + /* + * Current conf/call info. + */ + QString accountId_; + QString convUid_; + + QMetaObject::Connection callStatusChangedConnection_; + QMetaObject::Connection closeIncomingCallPageConnection_; + + /* + * For Call Overlay + */ + void setTime(const QString &accountId, const QString &convUid); + void updateCallOverlay(const lrc::api::conversation::Info &convInfo); + + QTimer *oneSecondTimer_; +}; diff --git a/src/clientwrapper.cpp b/src/clientwrapper.cpp new file mode 100644 index 00000000..f099de65 --- /dev/null +++ b/src/clientwrapper.cpp @@ -0,0 +1,103 @@ +/* + * Copyright (C) 2019-2020 by Savoir-faire Linux + * Author: Yang Wang + * + * 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 . + */ + +#include "clientwrapper.h" + +ClientWrapper::ClientWrapper(QObject *parent) + : QObject(parent) +{ + connect(getAccountAdapter(), &AccountAdapter::accountSignalsReconnect, [this]() { + emit accountModelChanged(); + emit avmodelChanged(); + emit dataTransferModelChanged(); + emit contactModelChanged(); + emit deviceModelChanged(); + }); +} + +NameDirectory * +ClientWrapper::getNameDirectory() +{ + return &(NameDirectory::instance()); +} + +UtilsAdapter * +ClientWrapper::getUtilsAdapter() +{ + return &(UtilsAdapter::instance()); +} + +SettingsAdaptor * +ClientWrapper::getSettingsAdaptor() +{ + return &(SettingsAdaptor::instance()); +} + +LRCInstance * +ClientWrapper::getLRCInstance() +{ + return &(LRCInstance::instance()); +} + +AccountAdapter * +ClientWrapper::getAccountAdapter() +{ + return &(AccountAdapter::instance()); +} + +RenderManager * +ClientWrapper::getRenderManager() +{ + return LRCInstance::renderer(); +} + +lrc::api::NewAccountModel * +ClientWrapper::getAccountModel() +{ + return &(LRCInstance::accountModel()); +} + +lrc::api::AVModel * +ClientWrapper::getAvModel() +{ + return &(LRCInstance::avModel()); +} + +lrc::api::PluginModel * +ClientWrapper::getPluginModel() +{ + return &(LRCInstance::pluginModel()); +} + +lrc::api::DataTransferModel * +ClientWrapper::getDataTransferModel() +{ + return &(LRCInstance::dataTransferModel()); +} + +lrc::api::ContactModel * +ClientWrapper::getContactModel() +{ + return getSettingsAdaptor()->getCurrentAccountInfo().contactModel.get(); +} + +lrc::api::NewDeviceModel * +ClientWrapper::getDeviceModel() +{ + return getSettingsAdaptor()->getCurrentAccountInfo().deviceModel.get(); +} diff --git a/src/clientwrapper.h b/src/clientwrapper.h new file mode 100644 index 00000000..d6e321a9 --- /dev/null +++ b/src/clientwrapper.h @@ -0,0 +1,96 @@ +/* + * Copyright (C) 2019-2020 by Savoir-faire Linux + * Author: Yang Wang + * + * 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 . + */ + +#pragma once + +#include "accountadapter.h" +#include "accountlistmodel.h" +#include "audiocodeclistmodel.h" +#include "avadapter.h" +#include "bannedlistmodel.h" +#include "calladapter.h" +#include "contactadapter.h" +#include "conversationsadapter.h" +#include "deviceitemlistmodel.h" +#include "pluginitemlistmodel.h" +#include "preferenceitemlistmodel.h" +#include "distantrenderer.h" +#include "globalinstances.h" +#include "globalsystemtray.h" +#include "messagesadapter.h" +#include "namedirectory.h" +#include "pixbufmanipulator.h" +#include "previewrenderer.h" +#include "qrimageprovider.h" +#include "settingsadaptor.h" +#include "utils.h" +#include "version.h" +#include "videocodeclistmodel.h" + +#include + +class ClientWrapper : public QObject +{ + Q_OBJECT + + Q_PROPERTY(UtilsAdapter *utilsAdaptor READ getUtilsAdapter NOTIFY utilsAdaptorChanged) + Q_PROPERTY(SettingsAdaptor *settingsAdaptor READ getSettingsAdaptor NOTIFY settingsAdaptorChanged) + Q_PROPERTY(NameDirectory *nameDirectory READ getNameDirectory NOTIFY nameDirectoryChanged) + Q_PROPERTY(LRCInstance *lrcInstance READ getLRCInstance NOTIFY lrcInstanceChanged) + Q_PROPERTY(AccountAdapter *accountAdaptor READ getAccountAdapter NOTIFY accountAdaptorChanged) + Q_PROPERTY(RenderManager *renderManager READ getRenderManager NOTIFY renderManagerChanged) + Q_PROPERTY(lrc::api::NewAccountModel *accountModel READ getAccountModel NOTIFY accountModelChanged) + Q_PROPERTY(lrc::api::AVModel *avmodel READ getAvModel NOTIFY avmodelChanged) + Q_PROPERTY(lrc::api::DataTransferModel *dataTransferModel READ getDataTransferModel NOTIFY dataTransferModelChanged) + Q_PROPERTY(lrc::api::ContactModel *contactModel READ getContactModel NOTIFY contactModelChanged) + Q_PROPERTY(lrc::api::NewDeviceModel *deviceModel READ getDeviceModel NOTIFY deviceModelChanged) + Q_PROPERTY(lrc::api::PluginModel *pluginModel READ getPluginModel) +public: + explicit ClientWrapper(QObject *parent = nullptr); + + NameDirectory *getNameDirectory(); + UtilsAdapter *getUtilsAdapter(); + SettingsAdaptor *getSettingsAdaptor(); + LRCInstance *getLRCInstance(); + AccountAdapter *getAccountAdapter(); + + RenderManager *getRenderManager(); + lrc::api::NewAccountModel *getAccountModel(); + lrc::api::AVModel *getAvModel(); + lrc::api::DataTransferModel *getDataTransferModel(); + + lrc::api::ContactModel *getContactModel(); + lrc::api::NewDeviceModel *getDeviceModel(); + lrc::api::PluginModel *getPluginModel(); + +signals: + void utilsAdaptorChanged(); + void settingsAdaptorChanged(); + void nameDirectoryChanged(); + void lrcInstanceChanged(); + void accountAdaptorChanged(); + void renderManagerChanged(); + void accountModelChanged(); + void avmodelChanged(); + void dataTransferModelChanged(); + void contactModelChanged(); + void deviceModelChanged(); +}; +#if QT_VERSION >= QT_VERSION_CHECK(5, 8, 0) +Q_DECLARE_METATYPE(ClientWrapper *) +#endif diff --git a/src/commoncomponents/AccountMigrationDialog.qml b/src/commoncomponents/AccountMigrationDialog.qml new file mode 100644 index 00000000..af289003 --- /dev/null +++ b/src/commoncomponents/AccountMigrationDialog.qml @@ -0,0 +1,969 @@ +/* + * Copyright (C) 2019-2020 by Savoir-faire Linux + * Author: Yang Wang + * + * 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 . + */ + +import QtQuick 2.15 +import QtQuick.Window 2.15 +import QtQuick.Controls 2.15 +import QtQuick.Controls.Universal 2.12 +import QtQuick.Layouts 1.3 +import QtGraphicalEffects 1.14 +import net.jami.Models 1.0 + +import "../constant" +import "../wizardview/components" +/* + * Account Migration Dialog for migrating account + */ + +Window{ + id: accountMigrationDialog + + AccountsToMigrateListModel{ + id: accountsToMigrateListModel + } + + property string accountID: "" + property string password: "" + + property bool nonOperationClosing: true + property bool successState : true + property string imgBase64: "" + + signal accountMigrationFinished + + function startAccountMigrationOfTopStack(){ + passwordInputLineEdit.clear() + accountsToMigrateListModel.reset() + + if(accountsToMigrateListModel.rowCount() <= 0){ + closeWithoutOperation() + + return false + } + + var managerUsername = accountsToMigrateListModel.data(accountsToMigrateListModel.index( + 0, 0), AccountsToMigrateListModel.ManagerUsername) + var managerUri = accountsToMigrateListModel.data(accountsToMigrateListModel.index( + 0, 0), AccountsToMigrateListModel.ManagerUri) + var username = accountsToMigrateListModel.data(accountsToMigrateListModel.index( + 0, 0), AccountsToMigrateListModel.Username) + var alias = accountsToMigrateListModel.data(accountsToMigrateListModel.index( + 0, 0), AccountsToMigrateListModel.Alias) + + if(managerUri.length !== 0){ + managerUriInputLabel.text = managerUri + } else { + managerUriInputLabel.text = "N/A" + } + + if(username.length !== 0){ + usernameInputLabel.text = username + } else if(managerUsername.length !== 0){ + usernameInputLabel.text = managerUsername + } else { + usernameInputLabel.text = "N/A" + } + + if(alias.length !== 0){ + aliasInputLabel.text = alias + } else { + aliasInputLabel.text = "N/A" + } + + accountID = accountsToMigrateListModel.data(accountsToMigrateListModel.index( + 0, 0), AccountsToMigrateListModel.Account_ID) + + imgBase64 = accountsToMigrateListModel.data(accountsToMigrateListModel.index( + 0, 0), AccountsToMigrateListModel.Picture) + + connectionMigrationEnded.enabled = false + migrationPushButton.enabled = false + stackedWidget.currentIndex = 0 + + successState = true + nonOperationClosing = true + + accountMigrationDialog.show() + return true + } + + function checkIfAccountMigrationFinishedAndClose(){ + accountsToMigrateListModel.reset() + if(accountsToMigrateListModel.rowCount() > 0){ + startAccountMigrationOfTopStack() + } else { + accountMigrationFinished() + if(!nonOperationClosing){ + nonOperationClosing = true + accountMigrationDialog.close() + } + } + } + + function acceptMigration(){ + nonOperationClosing = false + accountsToMigrateListModel.dataChanged(accountsToMigrateListModel.index(0, 0), + accountsToMigrateListModel.index( + accountsToMigrateListModel.rowCount() - 1, 0)) + checkIfAccountMigrationFinishedAndClose() + } + + function refuseMigrationAndDeleteAccount(){ + ClientWrapper.accountModel.removeAccount(accountID) + acceptMigration() + } + + function closeWithoutOperation(){ + nonOperationClosing = false + accountMigrationDialog.close() + } + + Timer{ + id: timerFailureReturn + + interval: 1000 + repeat: false + + onTriggered: { + stackedWidget.currentIndex = 0 + successState = true + } + } + + Connections{ + id: connectionMigrationEnded + enabled: false + target: ClientWrapper.accountModel + + function onMigrationEnded(accountIdIn, ok){ + nonOperationClosing = true + connectionMigrationEnded.enabled = false + if(accountID !== accountIdIn){ + return + } + if(!ok){ + successState = false + timerFailureReturn.restart() + } else { + acceptMigration() + } + } + } + + function slotMigrationButtonClicked(){ + successState = true + stackedWidget.currentIndex = 1 + + connectionMigrationEnded.enabled = true + ClientWrapper.accountAdaptor.setArchivePasswordAsync(accountID,password) + } + + function slotDeleteButtonClicked(){ + nonOperationClosing = false + refuseMigrationAndDeleteAccount() + } + + onClosing: { + connectionMigrationEnded.enabled = false + stackedWidget.currentIndex = 0 + accountID = "" + password = "" + passwordInputLineEdit.clear() + managerUriInputLabel.text = "" + usernameInputLabel.text = "" + aliasInputLabel.text = "" + + if(nonOperationClosing){ + checkIfAccountMigrationFinishedAndClose() + } + nonOperationClosing = true + } + + visible: false + + width: 455 + height: 594 + + Component.onCompleted: { + setX(Screen.width / 2 - width / 2) + setY(Screen.height / 2 - height / 2) + } + + ColumnLayout { + anchors.fill: parent + Layout.alignment: Qt.AlignHCenter + + StackLayout{ + id: stackedWidget + + Layout.fillWidth: true + Layout.fillHeight: true + Layout.alignment: Qt.AlignHCenter + + currentIndex: 0 + + Rectangle{ + id: accountMigrationPage + + Layout.fillWidth: true + Layout.fillHeight: true + Layout.alignment: Qt.AlignHCenter + + Layout.leftMargin: 11 + Layout.rightMargin: 11 + Layout.topMargin: 11 + Layout.bottomMargin: 11 + + x: (parent.width - width) /2 + y: (parent.height - height) /2 + + ScrollView { + id: accountMigrationPageScroll + anchors.fill: parent + + clip: true + + ScrollBar.horizontal.policy: ScrollBar.AsNeeded + ScrollBar.vertical.policy: ScrollBar.AsNeeded + + ColumnLayout{ + spacing: 7 + + width: stackedWidget.width + height: stackedWidget.height + Layout.alignment: Qt.AlignHCenter + + RowLayout{ + Layout.fillWidth: true + + Item{ + Layout.fillWidth: true + + Layout.minimumHeight: 20 + Layout.preferredHeight: 20 + Layout.maximumHeight: 20 + } + + Label{ + id: accountMigrationLabel + + Layout.alignment: Qt.AlignHCenter + Layout.preferredHeight: 27 + + font.pointSize: 13 + font.kerning: true + wrapMode:Text.Wrap + + text: qsTr("Account Migration Required") + + horizontalAlignment: Text.AlignLeft + verticalAlignment: Text.AlignVCenter + } + + Item{ + Layout.fillWidth: true + + Layout.minimumHeight: 20 + Layout.preferredHeight: 20 + Layout.maximumHeight: 20 + } + } + + RowLayout{ + spacing: 7 + + Item{ + Layout.fillWidth: true + + Layout.minimumHeight: 20 + Layout.preferredHeight: 20 + Layout.maximumHeight: 20 + } + + Label{ + id: migrationReasonLabel + + Layout.alignment: Qt.AlignHCenter + Layout.preferredHeight: 21 + + font.pointSize: 10 + font.kerning: true + wrapMode:Text.Wrap + + text: qsTr("This account is malformed. Please enter your password") + + horizontalAlignment: Text.AlignLeft + verticalAlignment: Text.AlignVCenter + } + + Item{ + Layout.fillWidth: true + + Layout.minimumHeight: 20 + Layout.preferredHeight: 20 + Layout.maximumHeight: 20 + } + } + + Item{ + Layout.minimumWidth: 20 + Layout.preferredWidth: 20 + Layout.maximumWidth: 20 + + Layout.minimumHeight: 20 + Layout.preferredHeight: 20 + Layout.maximumHeight: 20 + } + + ColumnLayout{ + spacing: 7 + + Layout.fillWidth: true + + RowLayout{ + Layout.fillWidth: true + Layout.alignment: Qt.AlignCenter + + Item{ + Layout.fillWidth: true + + Layout.minimumHeight: 20 + Layout.preferredHeight: 20 + Layout.maximumHeight: 20 + } + + Label{ + id: avatarLabel + + Layout.maximumWidth: 200 + Layout.preferredWidth: 200 + Layout.minimumWidth: 200 + + Layout.maximumHeight: 200 + Layout.preferredHeight: 200 + Layout.minimumHeight: 200 + + Layout.alignment: Qt.AlignHCenter + + background: Rectangle { + id: avatarLabelBackground + + anchors.fill: parent + color: "transparent" + + Image{ + id: avatarImg + + anchors.fill: parent + source: { + if(imgBase64.length === 0){ + return "" + } else { + return "data:image/png;base64," + imgBase64 + } + } + fillMode: Image.PreserveAspectCrop + layer.enabled: true + layer.effect: OpacityMask { + maskSource: Rectangle{ + width: avatarImg.width + height: avatarImg.height + radius: { + var size = ((avatarImg.width <= avatarImg.height)? avatarImg.width:avatarImg.height) + return size /2 + } + } + } + } + } + } + + Item{ + Layout.fillWidth: true + + Layout.minimumHeight: 20 + Layout.preferredHeight: 20 + Layout.maximumHeight: 20 + } + } + } + + Item{ + Layout.minimumWidth: 20 + Layout.preferredWidth: 20 + Layout.maximumWidth: 20 + + Layout.minimumHeight: 30 + Layout.preferredHeight: 30 + Layout.maximumHeight: 30 + } + + GridLayout{ + rows: 4 + columns: 5 + rowSpacing: 7 + columnSpacing: 7 + + Layout.fillWidth: true + + // 1st Row + Item{ + Layout.row: 0 + Layout.column: 0 + + Layout.fillWidth: true + Layout.preferredWidth:40 + + Layout.minimumHeight: 20 + Layout.preferredHeight: 20 + Layout.maximumHeight: 20 + } + + Label{ + id: aliasLabel + + Layout.row: 0 + Layout.column: 1 + + Layout.preferredWidth: 92 + Layout.preferredHeight: 30 + + text: qsTr("Alias") + font.pointSize: 10 + font.kerning: true + + horizontalAlignment: Text.AlignLeft + verticalAlignment: Text.AlignVCenter + } + + Item{ + Layout.row: 0 + Layout.column: 2 + + Layout.fillWidth: true + Layout.preferredWidth:40 + Layout.maximumWidth: 40 + + Layout.minimumHeight: 20 + Layout.preferredHeight: 20 + Layout.maximumHeight: 20 + } + + Label{ + id: aliasInputLabel + + Layout.row: 0 + Layout.column: 3 + + Layout.preferredWidth: 142 + + Layout.minimumHeight: 30 + Layout.preferredHeight: 30 + + font.pointSize: 10 + font.kerning: true + + horizontalAlignment: Text.AlignLeft + verticalAlignment: Text.AlignVCenter + } + + Item{ + Layout.row: 0 + Layout.column: 4 + + Layout.fillWidth: true + Layout.preferredWidth:40 + + Layout.minimumHeight: 20 + Layout.preferredHeight: 20 + Layout.maximumHeight: 20 + } + + // 2nd Row + Item{ + Layout.row: 1 + Layout.column: 0 + + Layout.fillWidth: true + Layout.preferredWidth:40 + + Layout.minimumHeight: 20 + Layout.preferredHeight: 20 + Layout.maximumHeight: 20 + } + + Label{ + id: usernameLabel + + Layout.row: 1 + Layout.column: 1 + + Layout.preferredWidth: 92 + Layout.preferredHeight: 30 + + text: qsTr("Username") + font.pointSize: 10 + font.kerning: true + + horizontalAlignment: Text.AlignLeft + verticalAlignment: Text.AlignVCenter + } + + Item{ + Layout.row: 1 + Layout.column: 2 + + Layout.fillWidth: true + Layout.preferredWidth:40 + Layout.maximumWidth: 40 + + Layout.minimumHeight: 20 + Layout.preferredHeight: 20 + Layout.maximumHeight: 20 + } + + Label{ + id: usernameInputLabel + + Layout.row: 1 + Layout.column: 3 + + Layout.preferredWidth: 142 + + Layout.minimumHeight: 30 + Layout.preferredHeight: 30 + + font.pointSize: 10 + font.kerning: true + + horizontalAlignment: Text.AlignLeft + verticalAlignment: Text.AlignVCenter + } + + Item{ + Layout.row: 1 + Layout.column: 4 + + Layout.fillWidth: true + Layout.preferredWidth:40 + + Layout.minimumHeight: 20 + Layout.preferredHeight: 20 + Layout.maximumHeight: 20 + } + + // 3rd Row + Item{ + Layout.row: 2 + Layout.column: 0 + + Layout.fillWidth: true + Layout.preferredWidth:40 + + Layout.minimumHeight: 20 + Layout.preferredHeight: 20 + Layout.maximumHeight: 20 + } + + Label{ + id: managerUriLabel + + Layout.row: 2 + Layout.column: 1 + + Layout.preferredWidth: 92 + Layout.preferredHeight: 30 + + text: qsTr("Manager Uri") + font.pointSize: 10 + font.kerning: true + + horizontalAlignment: Text.AlignLeft + verticalAlignment: Text.AlignVCenter + } + + Item{ + Layout.row: 2 + Layout.column: 2 + + Layout.fillWidth: true + Layout.preferredWidth:40 + Layout.maximumWidth: 40 + + Layout.minimumHeight: 20 + Layout.preferredHeight: 20 + Layout.maximumHeight: 20 + } + + Label{ + id: managerUriInputLabel + + Layout.row: 2 + Layout.column: 3 + + Layout.preferredWidth: 142 + + Layout.minimumHeight: 30 + Layout.preferredHeight: 30 + + font.pointSize: 10 + font.kerning: true + + horizontalAlignment: Text.AlignLeft + verticalAlignment: Text.AlignVCenter + } + + Item{ + Layout.row: 2 + Layout.column: 4 + + Layout.fillWidth: true + Layout.preferredWidth:40 + + Layout.minimumHeight: 20 + Layout.preferredHeight: 20 + Layout.maximumHeight: 20 + } + + // 4th Row + Item{ + Layout.row: 3 + Layout.column: 0 + + Layout.fillWidth: true + Layout.preferredWidth:40 + + Layout.minimumHeight: 20 + Layout.preferredHeight: 20 + Layout.maximumHeight: 20 + } + + Label{ + id: passwordLabel + + Layout.row: 3 + Layout.column: 1 + + Layout.preferredWidth: 92 + Layout.preferredHeight: 30 + + text: qsTr("Password") + font.pointSize: 10 + font.kerning: true + + horizontalAlignment: Text.AlignLeft + verticalAlignment: Text.AlignVCenter + } + + Item{ + Layout.row: 3 + Layout.column: 2 + + Layout.fillWidth: true + Layout.preferredWidth:40 + Layout.maximumWidth: 40 + + Layout.minimumHeight: 20 + Layout.preferredHeight: 20 + Layout.maximumHeight: 20 + } + + InfoLineEdit{ + id: passwordInputLineEdit + + Layout.row: 3 + Layout.column: 3 + + Layout.preferredWidth: 142 + + Layout.minimumHeight: 30 + Layout.preferredHeight: 30 + + font.pointSize: 10 + font.kerning: true + + horizontalAlignment: Text.AlignLeft + verticalAlignment: Text.AlignVCenter + + echoMode: TextInput.Password + + placeholderText: qsTr("Password") + + onTextChanged: { + if(text.length === 0){ + migrationPushButton.enabled = false + } else { + migrationPushButton.enabled = true + } + password = text + } + + onEditingFinished: { + password = text + } + } + + Item{ + Layout.row: 3 + Layout.column: 4 + + Layout.fillWidth: true + Layout.preferredWidth:40 + + Layout.minimumHeight: 20 + Layout.preferredHeight: 20 + Layout.maximumHeight: 20 + } + } + + Item{ + Layout.minimumWidth: 20 + Layout.preferredWidth: 20 + Layout.maximumWidth: 20 + + Layout.minimumHeight: 40 + Layout.preferredHeight: 40 + Layout.maximumHeight: 40 + } + + RowLayout{ + spacing: 0 + Layout.fillWidth: true + + Item { + Layout.minimumWidth: 20 + Layout.preferredWidth: 20 + Layout.maximumWidth: 20 + + Layout.minimumHeight: 40 + Layout.preferredHeight: 40 + Layout.maximumHeight: 40 + } + + HoverableGradientButton { + id: migrationPushButton + + Layout.alignment: Qt.AlignLeft + Layout.maximumWidth: 100 + Layout.preferredWidth: 100 + + Layout.maximumHeight: 30 + Layout.preferredHeight: 30 + Layout.minimumHeight: 30 + + text: qsTr("Migrate") + font.pointSize: 10 + font.kerning: true + + radius: height / 2 + backgroundColor: JamiTheme.releaseColor + + onClicked: { + slotMigrationButtonClicked() + } + } + + Item { + Layout.fillWidth: true + + Layout.minimumHeight: 40 + Layout.preferredHeight: 40 + Layout.maximumHeight: 40 + } + + HoverableButtonTextItem { + id: deleteAccountPushButton + + backgroundColor: "red" + onEnterColor: Qt.rgba(150 / 256, 0, 0, 0.7) + onDisabledBackgroundColor: Qt.rgba( + 255 / 256, + 0, 0, 0.8) + onPressColor: backgroundColor + textColor: "white" + + Layout.alignment: Qt.AlignRight + Layout.maximumWidth: 100 + Layout.preferredWidth: 100 + + Layout.maximumHeight: 30 + Layout.preferredHeight: 30 + Layout.minimumHeight: 30 + + text: qsTr("Delete") + font.pointSize: 10 + font.kerning: true + + radius: height / 2 + + onClicked: { + slotDeleteButtonClicked() + } + } + + Item { + Layout.minimumWidth: 20 + Layout.preferredWidth: 20 + Layout.maximumWidth: 20 + + Layout.minimumHeight: 40 + Layout.preferredHeight: 40 + Layout.maximumHeight: 40 + } + } + } + + } + } + + Rectangle{ + id: migrationWaitingPage + + Layout.fillWidth: true + Layout.fillHeight: true + Layout.alignment: Qt.AlignHCenter + + Layout.leftMargin: 11 + Layout.rightMargin: 11 + Layout.topMargin: 11 + Layout.bottomMargin: 11 + + x: (parent.width - width) /2 + y: (parent.height - height) /2 + + ScrollView { + id: migrationWaitingPageScroll + anchors.fill: parent + + clip: true + + ScrollBar.horizontal.policy: ScrollBar.AsNeeded + ScrollBar.vertical.policy: ScrollBar.AsNeeded + + ColumnLayout{ + spacing: 7 + + width: stackedWidget.width + height: stackedWidget.height + Layout.alignment: Qt.AlignHCenter + + Item{ + Layout.fillWidth: true + Layout.fillHeight: true + + Layout.preferredHeight: 211 + } + + RowLayout{ + spacing: 7 + + Layout.alignment: Qt.AlignHCenter + Layout.fillWidth: true + + Item{ + Layout.alignment: Qt.AlignLeft + Layout.fillWidth: true + Layout.fillHeight: true + + Layout.minimumWidth: 20 + } + + Label{ + id: spinnerLabel + + Layout.alignment: Qt.AlignHCenter + + Layout.maximumWidth: 200 + Layout.preferredWidth: 200 + Layout.minimumWidth: 200 + + Layout.maximumHeight: 200 + Layout.preferredHeight: 200 + Layout.minimumHeight: 200 + + property string spinnerDisplyState: successState ? "spinnerLabel_Regular" : "spinnerLabel_Failure" + onSpinnerDisplyStateChanged: { + switch (spinnerDisplyState) { + case "spinnerLabel_Regular": + background = Qt.createQmlObject("import QtQuick 2.14; + AnimatedImage { + source: \"qrc:/images/jami_eclipse_spinner.gif\" + + playing: true + paused: false + fillMode: Image.PreserveAspectFit + mipmap: true + }", spinnerLabel) + break + case "spinnerLabel_Failure": + background = Qt.createQmlObject("import QtQuick 2.14; + import \"qrc:/src/constant/\"; + Image { + anchors.fill: parent; + source:\"image://tintedPixmap/\" + (\"qrc:/images/icons/baseline-error_outline-24px.svg\").replace(\"qrc:/images/icons/\", \"\") + \"+\" + JamiTheme.urgentOrange_; + mipmap: true;}", spinnerLabel) + break + } + } + } + + Item { + Layout.alignment: Qt.AlignRight + Layout.fillWidth: true + Layout.fillHeight: true + + Layout.minimumWidth: 20 + } + } + + Item{ + Layout.fillWidth: true + Layout.fillHeight: true + + Layout.preferredHeight: 211 + } + + Label{ + id: progressLabel + + Layout.alignment: Qt.AlignHCenter + Layout.fillWidth: true + + color: successState? "black" : "red" + text: successState? qsTr("Migrating your Jami account...") : qsTr("Migration Failed") + font.pointSize: 11 + font.kerning: true + + horizontalAlignment: Text.AlignHCenter + verticalAlignment: Text.AlignVCenter + wrapMode: Label.WordWrap + } + + Item{ + Layout.fillWidth: true + + Layout.minimumHeight: 20 + Layout.preferredHeight: 20 + Layout.maximumHeight: 20 + } + } + } + } + } + } +} diff --git a/src/commoncomponents/CustomBorder.qml b/src/commoncomponents/CustomBorder.qml new file mode 100644 index 00000000..1a2843e7 --- /dev/null +++ b/src/commoncomponents/CustomBorder.qml @@ -0,0 +1,54 @@ + +/* + * Copyright (C) 2020 by Savoir-faire Linux + * Author: Mingrui Zhang + * + * 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 . + */ +import QtQuick 2.14 + + +/* + * Inspired by + * https://stackoverflow.com/questions/16534489/qml-control-border-width-and-color-on-any-one-side-of-rectangle-element + */ +Rectangle { + + property bool commonBorder: true + + property int lBorderwidth: 1 + property int rBorderwidth: 1 + property int tBorderwidth: 1 + property int bBorderwidth: 1 + + property int commonBorderWidth: 1 + + z: -1 + + property string borderColor: "white" + + color: borderColor + + anchors { + left: parent.left + right: parent.right + top: parent.top + bottom: parent.bottom + + topMargin: commonBorder ? -commonBorderWidth : -tBorderwidth + bottomMargin: commonBorder ? -commonBorderWidth : -bBorderwidth + leftMargin: commonBorder ? -commonBorderWidth : -lBorderwidth + rightMargin: commonBorder ? -commonBorderWidth : -rBorderwidth + } +} diff --git a/src/commoncomponents/DeleteAccountDialog.qml b/src/commoncomponents/DeleteAccountDialog.qml new file mode 100644 index 00000000..1db2813b --- /dev/null +++ b/src/commoncomponents/DeleteAccountDialog.qml @@ -0,0 +1,254 @@ +/* + * Copyright (C) 2020 by Savoir-faire Linux + * Author: Yang Wang + * + * 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 . + */ + +import QtQuick 2.15 +import QtQuick.Controls 2.14 +import QtQuick.Layouts 1.14 +import QtQuick.Controls.Styles 1.4 +import net.jami.Models 1.0 + +Dialog { + id: deleteAccountDialog + + property int profileType: ClientWrapper.settingsAdaptor.getCurrentAccount_Profile_Info_Type() + + property bool isSIP: { + switch (profileType) { + case Profile.Type.SIP: + return true; + default: + return false; + } + } + + onOpened: { + profileType = ClientWrapper.settingsAdaptor.getCurrentAccount_Profile_Info_Type() + labelBestId.text = ClientWrapper.settingsAdaptor.getAccountBestName() + labelAccountHash.text = ClientWrapper.settingsAdaptor.getCurrentAccount_Profile_Info_Uri() + } + + onVisibleChanged: { + if(!visible){ + reject() + } + } + + visible: false + title: qsTr("Account deletion") + + contentItem: Rectangle{ + implicitWidth: 400 + implicitHeight: 300 + + ColumnLayout{ + anchors.fill: parent + spacing: 7 + + Layout.alignment: Qt.AlignCenter + + Label{ + id: labelDeletion + + Layout.topMargin: 11 + Layout.leftMargin: 11 + Layout.rightMargin: 11 + + Layout.alignment: Qt.AlignHCenter + font.pointSize: 8 + font.kerning: true + horizontalAlignment: Text.AlignHCenter + verticalAlignment: Text.AlignVCenter + wrapMode: Text.Wrap + text:qsTr("Do you really want to delete the following account?") + } + + Label{ + id: labelBestId + + Layout.leftMargin: 11 + Layout.rightMargin: 11 + + Layout.alignment: Qt.AlignHCenter + font.pointSize: 8 + font.kerning: true + font.bold: true + horizontalAlignment: Text.AlignHCenter + verticalAlignment: Text.AlignVCenter + wrapMode: Text.Wrap + + text: ClientWrapper.settingsAdaptor.getAccountBestName() + } + + Label{ + id: labelAccountHash + + Layout.leftMargin: 11 + Layout.rightMargin: 11 + + Layout.alignment: Qt.AlignHCenter + font.pointSize: 8 + font.kerning: true + horizontalAlignment: Text.AlignHCenter + verticalAlignment: Text.AlignVCenter + wrapMode: Text.Wrap + text: ClientWrapper.settingsAdaptor.getCurrentAccount_Profile_Info_Uri() + } + + Item{ + Layout.fillWidth: true + + Layout.leftMargin: 11 + Layout.rightMargin: 11 + + Layout.maximumHeight: 5 + Layout.preferredHeight: 5 + Layout.minimumHeight: 5 + } + + Label{ + id: labelWarning + + Layout.leftMargin: 11 + Layout.rightMargin: 11 + + Layout.preferredWidth: 300 + + visible: ! isSIP + + Layout.alignment: Qt.AlignHCenter + wrapMode: Text.Wrap + text: qsTr("If this account hasn't been exported, or added to another device, it will be irrevocably lost.") + font.pointSize: 8 + font.kerning: true + horizontalAlignment: Text.AlignHCenter + verticalAlignment: Text.AlignVCenter + color: "red" + } + + Item{ + Layout.fillWidth: true + + Layout.leftMargin: 11 + Layout.rightMargin: 11 + + Layout.maximumHeight: 10 + Layout.preferredHeight: 10 + Layout.minimumHeight: 10 + } + + RowLayout{ + spacing: 7 + + Layout.leftMargin: 11 + Layout.rightMargin: 11 + + Item{ + Layout.fillWidth: true + Layout.minimumWidth: 40 + + Layout.maximumHeight: 20 + Layout.preferredHeight: 20 + Layout.minimumHeight: 20 + } + + HoverableRadiusButton{ + id: btnDeleteAccept + + Layout.maximumWidth: 130 + Layout.preferredWidth: 130 + Layout.minimumWidth: 130 + + Layout.maximumHeight: 30 + Layout.preferredHeight: 30 + Layout.minimumHeight: 30 + + radius: height /2 + + text: qsTr("Delete") + font.pointSize: 10 + font.kerning: true + + onClicked: { + ClientWrapper.accountAdaptor.deleteCurrentAccount() + accept() + } + } + + Item{ + Layout.fillWidth: true + Layout.minimumWidth: 40 + + Layout.maximumHeight: 20 + Layout.preferredHeight: 20 + Layout.minimumHeight: 20 + } + + HoverableButtonTextItem{ + id: btnDeleteCancel + + Layout.maximumWidth: 130 + Layout.preferredWidth: 130 + Layout.minimumWidth: 130 + + Layout.maximumHeight: 30 + Layout.preferredHeight: 30 + Layout.minimumHeight: 30 + + backgroundColor: "red" + onEnterColor: Qt.rgba(150 / 256, 0, 0, 0.7) + onDisabledBackgroundColor: Qt.rgba( + 255 / 256, + 0, 0, 0.8) + onPressColor: backgroundColor + textColor: "white" + + radius: height /2 + + text: qsTr("Cancel") + font.pointSize: 10 + font.kerning: true + + onClicked: { + reject() + } + } + + Item{ + Layout.fillWidth: true + Layout.minimumWidth: 40 + + Layout.maximumHeight: 20 + Layout.preferredHeight: 20 + Layout.minimumHeight: 20 + } + } + + Item{ + Layout.fillWidth: true + + Layout.maximumHeight: 5 + Layout.preferredHeight: 5 + Layout.minimumHeight: 5 + + Layout.leftMargin: 11 + Layout.rightMargin: 11 + Layout.bottomMargin: 11 + } + } + } +} diff --git a/src/commoncomponents/GeneralMenuItem.qml b/src/commoncomponents/GeneralMenuItem.qml new file mode 100644 index 00000000..677c4b0e --- /dev/null +++ b/src/commoncomponents/GeneralMenuItem.qml @@ -0,0 +1,140 @@ + +/* + * Copyright (C) 2020 by Savoir-faire Linux + * Author: Mingrui Zhang + * + * 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 . + */ +import QtQuick 2.14 +import QtQuick.Controls 2.14 +import QtQuick.Layouts 1.14 +import net.jami.Models 1.0 + + +/* + * General menu item. + * Can control top, bottom, left, right border width. + * Use onClicked slot to simulate item click event. + * Can have image icon at the left of the text. + */ +MenuItem { + id: menuItem + + property string itemName: "" + property string iconSource: "" + property int preferredWidth: 150 + property int preferredHeight: 30 + property int topBorderWidth: 0 + property int bottomBorderWidth: 0 + property int leftBorderWidth: 0 + property int rightBorderWidth: 0 + + signal clicked + + contentItem: Rectangle { + id: menuItemContentRect + + anchors.fill: parent + + Image { + id: contextMenuItemImage + + anchors.left: menuItemContentRect.left + anchors.leftMargin: 5 + anchors.verticalCenter: menuItemContentRect.verticalCenter + + width: 25 + height: 25 + + visible: false + fillMode: Image.PreserveAspectFit + mipmap: true + } + + Text { + id: contextMenuItemText + + anchors.left: contextMenuItemImage.right + anchors.leftMargin: 5 + anchors.verticalCenter: menuItemContentRect.verticalCenter + width: textMetrics.boundingRect.width + height: 30 + + TextMetrics { + id: textMetrics + font: contextMenuItemText.font + elide: Text.ElideMiddle + elideWidth: contextMenuItemImage.visible ? (preferredWidth - contextMenuItemImage.width - 5) : preferredWidth + text: itemName + } + + text: textMetrics.elidedText + font.pointSize: JamiTheme.textFontSize - 3 + horizontalAlignment: Text.AlignLeft + verticalAlignment: Text.AlignVCenter + } + + color: "transparent" + } + + onIconSourceChanged: { + if (iconSource !== "") { + contextMenuItemImage.source = iconSource + contextMenuItemImage.visible = true + } + } + + background: Rectangle { + id: contextMenuBackgroundRect + + anchors.fill: parent + anchors.topMargin: topBorderWidth + anchors.bottomMargin: bottomBorderWidth + anchors.leftMargin: leftBorderWidth + anchors.rightMargin: rightBorderWidth + + implicitWidth: preferredWidth + implicitHeight: preferredHeight + + border.width: 0 + color: menuItem.down ? JamiTheme.releaseColor : "white" + + MouseArea { + anchors.fill: parent + hoverEnabled: true + onPressed: { + contextMenuBackgroundRect.color = JamiTheme.pressColor + } + onReleased: { + contextMenuBackgroundRect.color = JamiTheme.releaseColor + menuItem.clicked() + } + onEntered: { + contextMenuBackgroundRect.color = JamiTheme.hoverColor + } + onExited: { + contextMenuBackgroundRect.color = "white" + } + } + + CustomBorder { + commonBorder: false + lBorderwidth: leftBorderWidth + rBorderwidth: rightBorderWidth + tBorderwidth: topBorderWidth + bBorderwidth: bottomBorderWidth + borderColor: JamiTheme.tabbarBorderColor + } + } +} diff --git a/src/commoncomponents/GeneralMenuSeparator.qml b/src/commoncomponents/GeneralMenuSeparator.qml new file mode 100644 index 00000000..1a2e93dd --- /dev/null +++ b/src/commoncomponents/GeneralMenuSeparator.qml @@ -0,0 +1,38 @@ + +/* + * Copyright (C) 2020 by Savoir-faire Linux + * Author: Mingrui Zhang + * + * 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 . + */ +import QtQuick 2.14 +import QtQuick.Controls 2.14 +import net.jami.Models 1.0 + +MenuSeparator { + id: menuSeparator + + property int preferredWidth: 10 + property int preferredHeight: 1 + property string separatorColor: JamiTheme.tabbarBorderColor + + padding: 0 + topPadding: 1 + bottomPadding: 1 + contentItem: Rectangle { + implicitWidth: preferredWidth + implicitHeight: preferredHeight + color: separatorColor + } +} diff --git a/src/commoncomponents/HoverableButton.qml b/src/commoncomponents/HoverableButton.qml new file mode 100644 index 00000000..a7a4aaf9 --- /dev/null +++ b/src/commoncomponents/HoverableButton.qml @@ -0,0 +1,89 @@ + +/* + * Copyright (C) 2020 by Savoir-faire Linux + * Author: Mingrui Zhang + * + * 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 . + */ +import QtQuick 2.14 +import QtQuick.Controls 2.14 +import net.jami.Models 1.0 + + +/* + * HoverableButton contains the following configurable properties: + * 1. Color changes on different button state + * 2. Radius control (rounded) + * 3. Text content or image content + * 4. Can use OnClicked slot to implement some click logic + */ +Button { + id: hoverableButton + + property int fontPointSize: 9 + property int buttonImageHeight: hoverableButtonBackground.height - 10 + property int buttonImageWidth: hoverableButtonBackground.width - 10 + + property string backgroundColor: JamiTheme.releaseColor + property string onPressColor: JamiTheme.pressColor + property string onReleaseColor: JamiTheme.releaseColor + property string onEnterColor: JamiTheme.hoverColor + property string onExitColor: JamiTheme.releaseColor + + property alias radius: hoverableButtonBackground.radius + property alias source: hoverableButtonImage.source + + font.pointSize: fontPointSize + + hoverEnabled: true + + background: Rectangle { + id: hoverableButtonBackground + + color: backgroundColor + + Image { + id: hoverableButtonImage + + anchors.centerIn: hoverableButtonBackground + + height: buttonImageHeight + width: buttonImageWidth + + fillMode: Image.PreserveAspectFit + mipmap: true + asynchronous: true + } + + MouseArea { + anchors.fill: parent + + hoverEnabled: true + + onPressed: { + hoverableButtonBackground.color = onPressColor + } + onReleased: { + hoverableButtonBackground.color = onReleaseColor + hoverableButton.clicked() + } + onEntered: { + hoverableButtonBackground.color = onEnterColor + } + onExited: { + hoverableButtonBackground.color = onExitColor + } + } + } +} diff --git a/src/commoncomponents/HoverableButtonTextItem.qml b/src/commoncomponents/HoverableButtonTextItem.qml new file mode 100644 index 00000000..fc1d6bb0 --- /dev/null +++ b/src/commoncomponents/HoverableButtonTextItem.qml @@ -0,0 +1,103 @@ + +/* + * Copyright (C) 2020 by Savoir-faire Linux + * Author: Mingrui Zhang + * + * 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 . + */ +import QtQuick 2.14 +import QtQuick.Controls 2.14 +import net.jami.Models 1.0 + + +/* + * HoverableButton containes functionalites: + * 1. Color changes on different button state + * 2. Radius control (rounded) + * 3. Text content or image content + * 4. Can use OnClicked slot to implement some click logic + */ +Button { + id: hoverableButton + + property int fontPointSize: 9 + property int buttonImageHeight: hoverableButtonBackground.height - 10 + property int buttonImageWidth: hoverableButtonBackground.width - 10 + + property string backgroundColor: JamiTheme.releaseColor + property string onPressColor: JamiTheme.pressColor + property string onReleaseColor: backgroundColor + property string onEnterColor: JamiTheme.hoverColor + property string onExitColor: backgroundColor + property string onDisabledBackgroundColor: backgroundColor + property string textColor: "black" + + property alias radius: hoverableButtonBackground.radius + property alias source: hoverableButtonImage.source + + font.pointSize: fontPointSize + font.kerning: true + + hoverEnabled: true + + contentItem: Text { + text: hoverableButton.text + font: hoverableButton.font + opacity: enabled ? 1.0 : 0.3 + color: textColor + horizontalAlignment: Text.AlignHCenter + verticalAlignment: Text.AlignVCenter + elide: Text.ElideRight + } + + background: Rectangle { + id: hoverableButtonBackground + + color: hoverableButton.enabled ? backgroundColor:onDisabledBackgroundColor + + Image { + id: hoverableButtonImage + + anchors.centerIn: hoverableButtonBackground + + height: buttonImageHeight + width: buttonImageWidth + + fillMode: Image.PreserveAspectFit + mipmap: true + asynchronous: true + } + + MouseArea { + enabled: hoverableButton.enabled + anchors.fill: parent + + hoverEnabled: true + + onPressed: { + hoverableButtonBackground.color = onPressColor + } + onReleased: { + hoverableButtonBackground.color = onReleaseColor + hoverableButton.clicked() + } + onEntered: { + hoverableButtonBackground.color = onEnterColor + } + onExited: { + hoverableButtonBackground.color = onExitColor + } + } + } +} diff --git a/src/commoncomponents/HoverableRadiusButton.qml b/src/commoncomponents/HoverableRadiusButton.qml new file mode 100644 index 00000000..ef98e075 --- /dev/null +++ b/src/commoncomponents/HoverableRadiusButton.qml @@ -0,0 +1,93 @@ + +/* + * Copyright (C) 2020 by Savoir-faire Linux + * Author: Mingrui Zhang + * + * 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 . + */ +import QtQuick 2.15 +import QtQuick.Controls 2.14 +import net.jami.Models 1.0 + + +/* + * HoverableButton contains the following configurable properties: + * 1. Color changes on different button state + * 2. Radius control (rounded) + * 3. Text content or image content + * 4. Can use OnClicked slot to implement some click logic + */ +Button { + id: hoverableButton + property int fontPointSize: 9 + property int buttonImageHeight: hoverableButtonBackground.height - 10 + property int buttonImageWidth: hoverableButtonBackground.width - 10 + property string backgroundColor: JamiTheme.releaseColor + property string onPressColor: JamiTheme.pressColor + property string onReleaseColor: backgroundColor + property string onEnterColor: JamiTheme.hoverColor + property string onExitColor: backgroundColor + property alias radius: hoverableButtonBackground.radius + property alias source: hoverableButtonImage.source + property bool isHovering: false + radius: height / 2 + function enterBtn(){ + btnMouseArea.entered() + } + function exitBtn(){ + btnMouseArea.exited() + } + function pressBtn(){ + btnMouseArea.pressed() + } + function releaseBtn(){ + btnMouseArea.released() + } + font.pointSize: fontPointSize + font.kerning: true + hoverEnabled: true + background: Rectangle { + id: hoverableButtonBackground + color: backgroundColor + Image { + id: hoverableButtonImage + anchors.centerIn: hoverableButtonBackground + height: buttonImageHeight + width: buttonImageWidth + fillMode: Image.PreserveAspectFit + mipmap: true + asynchronous: true + } + MouseArea { + id: btnMouseArea + anchors.fill: parent + hoverEnabled: true + onPressed: { + hoverableButtonBackground.color = onPressColor + } + onReleased: { + hoverableButtonBackground.color = onReleaseColor + hoverableButton.clicked() + } + onEntered: { + hoverableButtonBackground.color = onEnterColor + isHovering = true + } + onExited: { + hoverableButtonBackground.color = onExitColor + isHovering = false + } + } + } +} diff --git a/src/commoncomponents/InfoLineEdit.qml b/src/commoncomponents/InfoLineEdit.qml new file mode 100644 index 00000000..cc50cdc8 --- /dev/null +++ b/src/commoncomponents/InfoLineEdit.qml @@ -0,0 +1,58 @@ +import QtQuick 2.14 +import QtQuick.Controls 2.14 +import QtQuick.Layouts 1.14 +import QtQuick.Controls.Styles 1.4 + +import "../constant" + +TextField{ + enum BorderColorMode{ + NORMAL, + RIGHT, + ERROR + } + + property int fieldLayoutWidth: 256 + property int fieldLayoutHeight: 30 + property bool layoutFillwidth: false + + property int borderColorMode: InfoLineEdit.NORMAL + property var backgroundColor: JamiTheme.rgb256(240,240,240) + property var borderColor: { + switch(borderColorMode){ + case InfoLineEdit.NORMAL: + return "transparent" + case InfoLineEdit.RIGHT: + return "green" + case InfoLineEdit.ERROR: + return "red" + } + } + + Layout.minimumHeight: fieldLayoutHeight + Layout.preferredHeight: fieldLayoutHeight + Layout.maximumHeight: fieldLayoutHeight + + Layout.minimumWidth: fieldLayoutWidth + Layout.maximumWidth: fieldLayoutWidth + Layout.preferredWidth: fieldLayoutWidth + + Layout.fillWidth: layoutFillwidth + Layout.alignment: Qt.AlignHCenter + + wrapMode: Text.Wrap + readOnly: false + selectByMouse: true + font.pointSize: 10 + font.kerning: true + horizontalAlignment: Text.AlignLeft + verticalAlignment: Text.AlignVCenter + + background: Rectangle { + anchors.fill: parent + radius: readOnly? 0 : height / 2 + border.color: readOnly? "transparent" : borderColor + border.width:readOnly? 0 : 2 + color: readOnly? "transparent" : backgroundColor + } +} diff --git a/src/commoncomponents/JamiFileDialog.qml b/src/commoncomponents/JamiFileDialog.qml new file mode 100644 index 00000000..2be31423 --- /dev/null +++ b/src/commoncomponents/JamiFileDialog.qml @@ -0,0 +1,51 @@ + +/* + * Copyright (C) 2020 by Savoir-faire Linux + * Author: Mingrui Zhang + * + * 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 . + */ +import QtQuick 2.14 +import Qt.labs.platform 1.1 + +FileDialog { + id: fileDialog + + + /* + * Use enum to avoid importing Qt.labs.platform when using JamiFileDialog. + */ + property int mode: JamiFileDialog.Mode.OpenFile + + enum Mode { + OpenFile = 0, + OpenFiles, + SaveFile + } + + title: "Please choose a file" + + onModeChanged: { + switch(mode) { + case JamiFileDialog.Mode.OpenFile: + fileDialog.fileMode = FileDialog.OpenFile + break + case JamiFileDialog.Mode.OpenFiles: + fileDialog.fileMode = FileDialog.OpenFiles + break + default: + fileDialog.fileMode = FileDialog.SaveFile + } + } +} diff --git a/src/commoncomponents/ListViewJami.qml b/src/commoncomponents/ListViewJami.qml new file mode 100644 index 00000000..c20cc8c3 --- /dev/null +++ b/src/commoncomponents/ListViewJami.qml @@ -0,0 +1,51 @@ +/* + * Copyright (C) 2019-2020 by Savoir-faire Linux + * Author: Yang Wang + * + * 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 . + */ + +import QtQuick 2.14 +import QtQuick.Window 2.14 +import QtQuick.Controls 2.14 +import QtQuick.Controls.Universal 2.12 +import QtQuick.Layouts 1.3 +import QtGraphicalEffects 1.14 +import QtQuick.Controls.Styles 1.4 +import net.jami.Models 1.0 + +Rectangle{ + id: listViewBackground + + property alias model: listView.model + property alias delegate: listView.delegate + property alias currentIndex: listView.currentIndex + + border.width: 1 + border.color: JamiTheme.hoverColor + + color: JamiTheme.releaseColor + + ListView{ + id: listView + + anchors.fill: parent + + visible: listViewBackground.visible + layer.mipmap: false + clip: true + + ScrollIndicator.vertical: ScrollIndicator {} + } +} diff --git a/src/commoncomponents/LookupStatusLabel.qml b/src/commoncomponents/LookupStatusLabel.qml new file mode 100644 index 00000000..1a9cf52b --- /dev/null +++ b/src/commoncomponents/LookupStatusLabel.qml @@ -0,0 +1,101 @@ +/* + * Copyright (C) 2019-2020 by Savoir-faire Linux + * Author: Yang Wang + * + * 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 . + */ + +import QtQuick 2.14 +import QtQuick.Layouts 1.3 +import QtQuick.Controls 2.14 + +Label { + id: lookupStatusLabel + + property int labelWidth : 30 + property int labelHeight : 30 + + Layout.maximumWidth: labelWidth + Layout.preferredWidth: labelWidth + Layout.minimumWidth: labelWidth + + Layout.maximumHeight: labelHeight + Layout.preferredHeight: labelHeight + Layout.minimumHeight: labelHeight + + property string lookupStatusState: "Blank" + + // whenever look up status state change, the backgroud weill be set to a cooresponding choice + onLookupStatusStateChanged: { + switch (lookupStatusState) { + case "Blank": + background = Qt.createQmlObject( + "import QtQuick 2.14; Rectangle { anchors.fill: parent; color: \"transparent\"; }", + lookupStatusLabel) + break + case "Invalid": + background = Qt.createQmlObject("import QtQuick 2.14; +import \"qrc:/src/constant/\"; +Rectangle { +anchors.fill: parent; +Image { +anchors.fill: parent; +source: \"image://tintedPixmap/\" + (\"qrc:/images/icons/baseline-error_outline-24px.svg\").replace(\"qrc:/images/icons/\",\"\") + \"+\" + JamiTheme.urgentOrange_; +mipmap: true; +} +}", lookupStatusLabel) + break + case "Taken": + background = Qt.createQmlObject("import QtQuick 2.14; +import \"qrc:/src/constant/\"; +Rectangle { +anchors.fill: parent; +Image{ +anchors.fill: parent; +source: \"image://tintedPixmap/\" + (\"qrc:/images/icons/baseline-close-24px.svg\").replace(\"qrc:/images/icons/\",\"\") + \"+\" + JamiTheme.red_; +mipmap: true; +} +}", lookupStatusLabel) + break + case "Free": + background = Qt.createQmlObject("import QtQuick 2.14; +import \"qrc:/src/constant/\"; +Rectangle { +anchors.fill: parent; +Image { +anchors.fill: parent; +source: \"image://tintedPixmap/\"+ (\"qrc:/images/icons/baseline-done-24px.svg\").replace(\"qrc:/images/icons/\",\"\") + \"+\" + JamiTheme.presenceGreen_; +mipmap: true; +} +}", lookupStatusLabel) + break + case "Searching": + background = Qt.createQmlObject("import QtQuick 2.14; +import \"qrc:/src/constant/\"; +Rectangle { +anchors.fill: parent; +AnimatedImage { +anchors.fill: parent +source: \"qrc:/images/jami_rolling_spinner.gif\"; + +playing: true +paused: false +fillMode: Image.PreserveAspectFit +mipmap: true +} +}", lookupStatusLabel) + break + } + } +} diff --git a/src/commoncomponents/MessageBox.qml b/src/commoncomponents/MessageBox.qml new file mode 100644 index 00000000..9e87c924 --- /dev/null +++ b/src/commoncomponents/MessageBox.qml @@ -0,0 +1,42 @@ +/* + * Copyright (C) 2020 by Savoir-faire Linux + * Author: Yang Wang + * + * 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 . + */ + +import QtQuick 2.15 +import QtQuick.Controls 2.14 +import QtQuick.Layouts 1.14 +import QtQuick.Controls.Styles 1.4 +import QtQuick.Dialogs 1.3 + +MessageDialog { + id: messageBox + + visible: false + modality: Qt.NonModal + width: 300 + height: 200 + + onRejected: {} + + function openWithParameters(titleToDisplay, infoToDisplay, infoIconMode = StandardIcon.Information, buttons = StandardButton.Ok){ + title = titleToDisplay + text = infoToDisplay + icon = infoIconMode + standardButtons = buttons + messageBox.open() + } +} diff --git a/src/commoncomponents/PasswordDialog.qml b/src/commoncomponents/PasswordDialog.qml new file mode 100644 index 00000000..28eced61 --- /dev/null +++ b/src/commoncomponents/PasswordDialog.qml @@ -0,0 +1,372 @@ +/* + * Copyright (C) 2020 by Savoir-faire Linux + * Author: Yang Wang + * + * 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 . + */ + +import QtQuick 2.15 +import QtQuick.Controls 2.14 +import QtQuick.Layouts 1.14 +import QtQuick.Controls.Styles 1.4 +import net.jami.Models 1.0 + +import "../constant" +/* + * PasswordDialog for changing password and exporting account + */ +Dialog { + id: passwordDialog + + enum PasswordEnteringPurpose { + ChangePassword, + ExportAccount, + SetPassword + } + readonly property int successCode: 200 + signal doneSignal(int code, int currentPurpose) + + property string path: "" + property int purpose: PasswordDialog.ChangePassword + + title: { + switch(purpose){ + case PasswordDialog.ExportAccount: + return qsTr("Enter the password of this account") + case PasswordDialog.ChangePassword: + return qsTr("Changing password") + case PasswordDialog.SetPassword: + return qsTr("Set password") + } + } + + function openDialog(purposeIn, exportPathIn = ""){ + purpose = purposeIn + path = exportPathIn + currentPasswordEdit.clear() + passwordEdit.clear() + confirmPasswordEdit.clear() + passwordDialog.open() + } + + function haveDone(code, currentPurpose) { + done(code) + doneSignal(code, currentPurpose) + } + + function validatePassword() { + var acceptablePassword = (passwordEdit.text === confirmPasswordEdit.text) + btnChangePasswordConfirm.enabled = acceptablePassword + + if (acceptablePassword) { + passwordEdit.borderColorMode = InfoLineEdit.RIGHT + confirmPasswordEdit.borderColorMode = InfoLineEdit.RIGHT + return + } + + passwordEdit.borderColorMode = InfoLineEdit.ERROR + confirmPasswordEdit.borderColorMode = InfoLineEdit.ERROR + } + + Timer{ + id: timerToOperate + + interval: 200 + repeat: false + + onTriggered: { + if ((purpose === PasswordDialog.ChangePassword) || (purpose === PasswordDialog.SetPassword)) { + savePasswordQML() + } else if(purpose === PasswordDialog.ExportAccount) { + exportAccountQML() + } + } + } + + function exportAccountQML() { + var success = false + if(path.length > 0){ + success = ClientWrapper.accountAdaptor.exportToFile(ClientWrapper.utilsAdaptor.getCurrAccId(),path,currentPasswordEdit.text) + } + + spinnerMovie.playing = false + spinnerLabel.visible = false + if (success) { + haveDone(successCode, passwordDialog.purpose) + } else { + currentPasswordEdit.clear() + btnChangePasswordConfirm.enabled = false + wrongPasswordLabel.visible = true + } + } + function savePasswordQML() { + var success = false + success = ClientWrapper.accountAdaptor.savePassword(ClientWrapper.utilsAdaptor.getCurrAccId(),currentPasswordEdit.text, passwordEdit.text) + + spinnerMovie.playing = false + spinnerLabel.visible = false + if (success) { + ClientWrapper.accountAdaptor.setArchiveHasPassword(passwordEdit.text.length !== 0) + haveDone(successCode, passwordDialog.purpose) + } else { + currentPasswordEdit.clear() + btnChangePasswordConfirm.enabled = false + wrongPasswordLabel.visible = true + } + } + + visible: false + + anchors.centerIn: parent.Center + x: (parent.width - width) / 2 + y: (parent.height - height) / 2 + + contentItem: Rectangle{ + implicitWidth: 440 + implicitHeight: 270 + + ColumnLayout { + anchors.fill: parent + spacing: 7 + + ColumnLayout { + Layout.topMargin: 11 + Layout.leftMargin: 40 + Layout.rightMargin: 40 + Layout.alignment: Qt.AlignHCenter + Layout.fillWidth: true + + Layout.preferredWidth: 360 + Layout.maximumWidth: 360 + spacing: 7 + + ColumnLayout { + spacing: 0 + + Layout.alignment: Qt.AlignHCenter + + Layout.preferredWidth: 356 + Layout.maximumWidth: 356 + + InfoLineEdit { + id: currentPasswordEdit + + Layout.minimumHeight: 30 + Layout.preferredHeight: 30 + Layout.maximumHeight: 30 + Layout.fillWidth: true + + visible: purpose === PasswordDialog.ChangePassword + echoMode: TextInput.Password + font.pointSize: 10 + font.kerning: true + horizontalAlignment: Text.AlignLeft + verticalAlignment: Text.AlignVCenter + + placeholderText: qsTr("Enter Current Password") + + onTextChanged: { + if (purpose === PasswordDialog.ChangePassword) { + validatePassword() + } + + if (currentPasswordEdit.text.length == 0) { + btnChangePasswordConfirm.enabled = false + } else { + wrongPasswordLabel.visible = false + btnChangePasswordConfirm.enabled = true + } + } + } + + Label { + id: wrongPasswordLabel + + Layout.alignment: Qt.AlignHCenter + + Layout.minimumHeight: 12 + Layout.preferredHeight: 12 + Layout.maximumHeight: 12 + Layout.fillWidth: true + + font.pointSize: 8 + font.kerning: true + horizontalAlignment: Text.AlignHCenter + verticalAlignment: Text.AlignVCenter + + text: qsTr("Current Password Incorrect") + color: "red" + + visible: false + } + } + + Item { + Layout.fillWidth: true + + Layout.minimumHeight: 8 + Layout.preferredHeight: 8 + Layout.maximumHeight: 8 + } + + InfoLineEdit { + id: passwordEdit + + fieldLayoutHeight: 30 + layoutFillwidth: true + + visible: purpose === PasswordDialog.ChangePassword || purpose === PasswordDialog.SetPassword + echoMode: TextInput.Password + font.pointSize: 10 + font.kerning: true + horizontalAlignment: Text.AlignLeft + verticalAlignment: Text.AlignVCenter + + placeholderText: qsTr("Enter New Password") + + onTextChanged: { + validatePassword() + } + } + + Item { + Layout.fillWidth: true + + Layout.minimumHeight: 8 + Layout.preferredHeight: 8 + Layout.maximumHeight: 8 + } + + InfoLineEdit { + id: confirmPasswordEdit + + fieldLayoutHeight: 30 + layoutFillwidth: true + + visible: purpose === PasswordDialog.ChangePassword || purpose === PasswordDialog.SetPassword + echoMode: TextInput.Password + font.pointSize: 10 + font.kerning: true + horizontalAlignment: Text.AlignLeft + verticalAlignment: Text.AlignVCenter + + placeholderText: qsTr("Confirm New Password") + + onTextChanged: { + validatePassword() + } + } + } + + Label { + id: spinnerLabel + + visible: false + + Layout.fillWidth: true + + Layout.minimumHeight: 20 + Layout.preferredHeight: 20 + Layout.maximumHeight: 20 + + background: Rectangle { + anchors.fill: parent + AnimatedImage { + id: spinnerMovie + + anchors.fill: parent + + source: "qrc:/images/ajax-loader.gif" + + playing: spinnerLabel.visible + paused: false + fillMode: Image.PreserveAspectFit + mipmap: true + } + } + } + + RowLayout { + spacing: 7 + + Layout.bottomMargin: 11 + Layout.fillWidth: true + + Layout.leftMargin: 30 + Layout.rightMargin: 30 + + HoverableRadiusButton { + id: btnChangePasswordConfirm + + Layout.maximumWidth: 130 + Layout.preferredWidth: 130 + Layout.minimumWidth: 130 + + Layout.minimumHeight: 30 + Layout.preferredHeight: 30 + Layout.maximumHeight: 30 + + text: qsTr("Confirm") + font.pointSize: 10 + font.kerning: true + + radius: height / 2 + + enabled: false + + onClicked: { + spinnerLabel.visible = true + spinnerMovie.playing = true + timerToOperate.restart() + } + } + + Item { + Layout.fillWidth: true + Layout.fillHeight: true + } + + HoverableButtonTextItem { + id: btnChangePasswordCancel + + Layout.maximumWidth: 130 + Layout.preferredWidth: 130 + Layout.minimumWidth: 130 + + Layout.minimumHeight: 30 + Layout.preferredHeight: 30 + Layout.maximumHeight: 30 + + backgroundColor: "red" + onEnterColor: Qt.rgba(150 / 256, 0, 0, 0.7) + onDisabledBackgroundColor: Qt.rgba( + 255 / 256, + 0, 0, 0.8) + onPressColor: backgroundColor + textColor: "white" + + text: qsTr("Cancel") + font.pointSize: 10 + font.kerning: true + + radius: height / 2 + + onClicked: { + passwordDialog.reject() + } + } + } + } + } +} diff --git a/src/commoncomponents/PhotoboothView.qml b/src/commoncomponents/PhotoboothView.qml new file mode 100644 index 00000000..4b006fa9 --- /dev/null +++ b/src/commoncomponents/PhotoboothView.qml @@ -0,0 +1,280 @@ +import QtQuick 2.14 +import QtQuick.Controls 2.14 +import QtQuick.Layouts 1.14 +import QtQuick.Controls.Styles 1.4 +import Qt.labs.platform 1.1 +import QtGraphicalEffects 1.0 +import net.jami.Models 1.0 + +ColumnLayout{ + property bool takePhotoState: false + property bool hasAvatar: false + property bool isDefaultIcon: false + property string imgBase64: "" + property string fileName: "" + + property int boothWidht: 224 + + signal imageAcquired + signal imageCleared + + function startBooth(force = false){ + hasAvatar = false + ClientWrapper.accountAdaptor.startPreviewing(force) + takePhotoState = true + } + + function stopBooth(){ + try{ + if(!ClientWrapper.accountAdaptor.hasVideoCall()) { + ClientWrapper.accountAdaptor.stopPreviewing() + } + } catch(erro){console.log("Exception: " + erro.message)} + + takePhotoState = false + } + + function setAvatarPixmap(avatarPixmapBase64, defaultValue = false){ + imgBase64 = avatarPixmapBase64 + stopBooth() + if(defaultValue){ + isDefaultIcon = defaultValue + } + } + + onVisibleChanged: { + if(!visible){ + stopBooth() + } + } + + JamiFileDialog{ + id: importFromFileToAvatar_Dialog + + mode: JamiFileDialog.OpenFile + title: qsTr("Choose an image to be the avatar") + folder: StandardPaths.writableLocation(StandardPaths.PicturesLocation) + + nameFilters: [ qsTr("Image Files") + " (*.png *.jpg *.jpeg)",qsTr( + "All files") + " (*)"] + + onAccepted: { + fileName = file + if(fileName.length === 0) { + imageCleared() + return + } + imgBase64 = ClientWrapper.utilsAdaptor.getCroppedImageBase64FromFile( + ClientWrapper.utilsAdaptor.getAbsPath(fileName),boothWidht) + imageAcquired() + stopBooth() + } + } + + spacing: 0 + + Layout.maximumWidth: boothWidht + Layout.preferredWidth: boothWidht + Layout.minimumWidth: boothWidht + + Layout.maximumHeight: 0 + + Layout.alignment: Qt.AlignHCenter + + Label{ + id: avatarLabel + + visible: !takePhotoState + + Layout.maximumWidth: boothWidht + Layout.preferredWidth: boothWidht + Layout.minimumWidth: boothWidht + + Layout.maximumHeight: boothWidht + Layout.preferredHeight: boothWidht + Layout.minimumHeight: boothWidht + + Layout.alignment: Qt.AlignHCenter + + background: Rectangle { + id: avatarLabelBackground + + anchors.fill: parent + color: "transparent" + + Image{ + id: avatarImg + + anchors.fill: parent + source: { + if(imgBase64.length === 0){ + return "" + } else { + return "data:image/png;base64," + imgBase64 + } + } + fillMode: Image.PreserveAspectCrop + layer.enabled: true + layer.effect: OpacityMask { + maskSource: Rectangle{ + width: avatarImg.width + height: avatarImg.height + radius: { + var size = ((avatarImg.width <= avatarImg.height)? avatarImg.width:avatarImg.height) + return size /2 + } + } + } + } + } + } + + PhotoboothPreviewRender{ + id:previewWidget + + onHideBooth:{ + stopBooth() + } + visible: takePhotoState + focus: visible + + Layout.alignment: Qt.AlignHCenter + Layout.maximumWidth: boothWidht + Layout.preferredWidth: boothWidht + Layout.minimumWidth: boothWidht + + Layout.maximumHeight: boothWidht + Layout.preferredHeight: boothWidht + Layout.minimumHeight: boothWidht + + layer.enabled: true + layer.effect: OpacityMask { + maskSource: Rectangle{ + width: previewWidget.width + height: previewWidget.height + radius: { + var size = ((previewWidget.width <= previewWidget.height)? previewWidget.width:previewWidget.height) + return size /2 + } + } + } + + Label{ + id: flashOverlay + + anchors.fill: previewWidget + visible: false + color: "#fff" + + OpacityAnimator on opacity{ + id: flashAnimation + + from: 1 + to: 0 + duration: 600 + } + } + } + + + RowLayout{ + Layout.fillWidth: true + Layout.minimumHeight: 30 + Layout.maximumHeight: 30 + + Item{ + Layout.fillWidth: true + Layout.fillHeight: true + } + + HoverableButton { + id: takePhotoButton + + property string cameraAltIconUrl: "qrc:/images/icons/baseline-camera_alt-24px.svg" + property string addPhotoIconUrl: "qrc:/images/icons/round-add_a_photo-24px.svg" + property string refreshIconUrl: "qrc:/images/icons/baseline-refresh-24px.svg" + + Layout.maximumWidth: 30 + Layout.preferredWidth: 30 + Layout.minimumWidth: 30 + + Layout.minimumHeight: 30 + Layout.preferredHeight: 30 + Layout.maximumHeight: 30 + + text: "" + font.pointSize: 10 + font.kerning: true + + radius: height / 6 + source: { + if(isDefaultIcon){ + return addPhotoIconUrl + } + + if(takePhotoState) { + return cameraAltIconUrl + } + + if(hasAvatar){ + return refreshIconUrl + } else { + return addPhotoIconUrl + } + } + onClicked: { + if(!takePhotoState){ + imageCleared() + startBooth() + return + } else { + // show flash overlay + flashOverlay.visible = true + flashAnimation.restart() + + // run concurrent function call to take photo + imgBase64 = previewWidget.takeCroppedPhotoToBase64(boothWidht) + hasAvatar = true + imageAcquired() + stopBooth() + } + } + } + + Item{ + Layout.fillHeight: true + + Layout.minimumWidth: 6 + Layout.preferredWidth: 6 + Layout.maximumWidth: 6 + } + + HoverableButton { + id: importButton + + Layout.maximumWidth: 30 + Layout.preferredWidth: 30 + Layout.minimumWidth: 30 + + Layout.minimumHeight: 30 + Layout.preferredHeight: 30 + Layout.maximumHeight: 30 + + text: "" + font.pointSize: 10 + font.kerning: true + + radius: height / 6 + source: "qrc:/images/icons/round-folder-24px.svg" + + onClicked: { + importFromFileToAvatar_Dialog.open() + } + } + + Item{ + Layout.fillWidth: true + Layout.fillHeight: true + } + } +} diff --git a/src/commoncomponents/TintedButton.qml b/src/commoncomponents/TintedButton.qml new file mode 100644 index 00000000..eaec9944 --- /dev/null +++ b/src/commoncomponents/TintedButton.qml @@ -0,0 +1,125 @@ + +/* + * Copyright (C) 2020 by Savoir-faire Linux + * Author: Mingrui Zhang + * + * 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 . + */ +import QtQuick 2.14 +import QtQuick.Controls 2.14 +import net.jami.Models 1.0 + +Button { + id: tintedButton + + + /* + * TintColor, color for the pixmap when button is hovered. + */ + property string tintColor: "white" + + + /* + * NormalPixmapSource - icons in normal state (non-toggled). + * SelectedPixmapSource - icons once button is toggled. + */ + property string normalPixmapSource: "" + property string selectedPixmapSource: "" + + + /* + * IsSelected property is to help set button current state manually. + */ + property bool isSelected: false + + + /* + * ButtonEntered signal is to help call overlay change its opacity + */ + signal buttonEntered + + function setChecked(checked) { + isSelected = checked + if (isSelected) { + tintedButtonImage.source = selectedPixmapSource + } else { + tintedButtonImage.source = normalPixmapSource + } + } + + hoverEnabled: true + + background: Rectangle { + id: tintedButtonBackground + + radius: 30 + color: "transparent" + + Image { + id: tintedButtonImage + + anchors.centerIn: tintedButtonBackground + + height: tintedButtonBackground.height - 10 + width: tintedButtonBackground.width - 10 + + source: normalPixmapSource + fillMode: Image.PreserveAspectFit + mipmap: true + asynchronous: true + } + + MouseArea { + anchors.fill: parent + + hoverEnabled: true + + onReleased: { + isSelected = !isSelected + if (isSelected) { + tintedButtonImage.source = "image://tintedPixmap/" + + selectedPixmapSource.replace( + "qrc:/images/icons/", "") + "+" + tintColor + } else { + tintedButtonImage.source = "image://tintedPixmap/" + normalPixmapSource.replace( + "qrc:/images/icons/", "") + "+" + tintColor + } + tintedButton.clicked() + } + onEntered: { + + + /* + * Tinted. + */ + if (isSelected) { + tintedButtonImage.source = "image://tintedPixmap/" + + selectedPixmapSource.replace( + "qrc:/images/icons/", "") + "+" + tintColor + } else { + tintedButtonImage.source = "image://tintedPixmap/" + normalPixmapSource.replace( + "qrc:/images/icons/", "") + "+" + tintColor + } + tintedButton.buttonEntered() + } + onExited: { + if (isSelected) { + tintedButtonImage.source = selectedPixmapSource + } else { + tintedButtonImage.source = normalPixmapSource + } + } + } + } +} diff --git a/src/connectivitymonitor.cpp b/src/connectivitymonitor.cpp new file mode 100644 index 00000000..0446223d --- /dev/null +++ b/src/connectivitymonitor.cpp @@ -0,0 +1,167 @@ +/* + * Copyright (C) 2019-2020 by Savoir-faire Linux + * Author: Andreas Traczyk + * + * 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 . + */ + +#include "connectivitymonitor.h" + +#include + +#ifdef Q_OS_WIN +#include +#include + +class NetworkEventHandler : public INetworkListManagerEvents +{ +public: + NetworkEventHandler() + : m_lRefCnt(1){}; + virtual ~NetworkEventHandler(){}; + + HRESULT STDMETHODCALLTYPE + QueryInterface(REFIID riid, void **ppvObject) + { + HRESULT hr = S_OK; + if (IsEqualIID(riid, IID_IUnknown)) { + *ppvObject = (IUnknown *) this; + } else if (IsEqualIID(riid, IID_INetworkListManagerEvents)) { + *ppvObject = (INetworkListManagerEvents *) this; + } else { + hr = E_NOINTERFACE; + } + + return hr; + }; + ULONG STDMETHODCALLTYPE + AddRef() + { + return (ULONG) InterlockedIncrement(&m_lRefCnt); + }; + ULONG STDMETHODCALLTYPE + Release() + { + LONG res = InterlockedDecrement(&m_lRefCnt); + if (res == 0) { + delete this; + } + return (ULONG) res; + }; + + virtual HRESULT STDMETHODCALLTYPE + ConnectivityChanged(NLM_CONNECTIVITY newConnectivity) + { + qDebug() << "connectivity changed: " << newConnectivity; + if (connectivityChangedCb_) { + connectivityChangedCb_(); + } + return S_OK; + }; + + void + setOnConnectivityChangedCallBack(std::function &&cb) + { + connectivityChangedCb_ = cb; + }; + +private: + LONG m_lRefCnt; + + std::function connectivityChangedCb_; +}; + +ConnectivityMonitor::ConnectivityMonitor(QObject *parent) + : QObject(parent) +{ + CoInitialize(NULL); + + IUnknown *pUnknown = NULL; + + HRESULT hr = CoCreateInstance(CLSID_NetworkListManager, + NULL, + CLSCTX_ALL, + IID_IUnknown, + (void **) &pUnknown); + if (FAILED(hr)) { + return; + } + + pNetworkListManager_ = NULL; + hr = pUnknown->QueryInterface(IID_INetworkListManager, (void **) &pNetworkListManager_); + if (FAILED(hr)) { + destroy(); + pUnknown->Release(); + return; + } + + pCPContainer_ = NULL; + hr = pNetworkListManager_->QueryInterface(IID_IConnectionPointContainer, + (void **) &pCPContainer_); + if (FAILED(hr)) { + destroy(); + pUnknown->Release(); + return; + } + + pConnectPoint_ = NULL; + hr = pCPContainer_->FindConnectionPoint(IID_INetworkListManagerEvents, &pConnectPoint_); + if (SUCCEEDED(hr)) { + cookie_ = NULL; + netEventHandler_ = new NetworkEventHandler; + netEventHandler_->setOnConnectivityChangedCallBack([this] { emit connectivityChanged(); }); + hr = pConnectPoint_->Advise((IUnknown *) netEventHandler_, &cookie_); + } else { + destroy(); + } + + pUnknown->Release(); +} + +bool +ConnectivityMonitor::isOnline() +{ + if (!pNetworkListManager_) { + return false; + } + VARIANT_BOOL IsConnect = VARIANT_FALSE; + HRESULT hr = pNetworkListManager_->get_IsConnectedToInternet(&IsConnect); + if (SUCCEEDED(hr)) { + return IsConnect == VARIANT_TRUE; + } + return false; +} + +void +ConnectivityMonitor::destroy() +{ + if (pConnectPoint_) { + pConnectPoint_->Unadvise(cookie_); + pConnectPoint_->Release(); + } + if (pCPContainer_) { + pCPContainer_->Release(); + } + if (pNetworkListManager_) { + pNetworkListManager_->Release(); + pNetworkListManager_ = NULL; + } +} + +ConnectivityMonitor::~ConnectivityMonitor() +{ + destroy(); + CoUninitialize(); +} +#endif // Q_OS_WIN \ No newline at end of file diff --git a/src/connectivitymonitor.h b/src/connectivitymonitor.h new file mode 100644 index 00000000..62865dd8 --- /dev/null +++ b/src/connectivitymonitor.h @@ -0,0 +1,46 @@ +/* + * Copyright (C) 2019-2020 by Savoir-faire Linux + * Author: Andreas Traczyk + * + * 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 . + */ + +#pragma once + +#include + +#ifdef Q_OS_WIN +class ConnectivityMonitor : public QObject +{ + Q_OBJECT + +public: + explicit ConnectivityMonitor(QObject *parent = 0); + ~ConnectivityMonitor(); + + bool isOnline(); + +signals: + void connectivityChanged(); + +private: + void destroy(); + + struct INetworkListManager *pNetworkListManager_; + struct IConnectionPointContainer *pCPContainer_; + struct IConnectionPoint *pConnectPoint_; + class NetworkEventHandler *netEventHandler_; + unsigned long cookie_; +}; +#endif // Q_OS_WIN \ No newline at end of file diff --git a/src/constant/JamiTheme.qml b/src/constant/JamiTheme.qml new file mode 100644 index 00000000..983ae0de --- /dev/null +++ b/src/constant/JamiTheme.qml @@ -0,0 +1,105 @@ + +/* + * Copyright (C) 2020 by Savoir-faire Linux + * Author: Mingrui Zhang + * + * 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 . + */ + + +/* + * JamiTheme as a singleton is to provide global property entry + * https://doc.qt.io/qt-5/qqmlengine.html#qmlRegisterSingletonType-3 + */ +pragma Singleton + +import QtQuick 2.14 + +Item { + + + /* + * Color strings. + */ + property string hoverColor: "#c7c7c7" + property string pressColor: "#c0c0c0" + property string releaseColor: "#e0e0e0" + property string tabbarBorderColor: "#e3e3e3" + property string transparentColor: "transparent" + property string presenceGreen: "#4cd964" + property string notificationRed: "#ff3b30" + + property string screenSelectionBorderGreen: "green" + + property string acceptButtonGreen: "#4caf50" + property string acceptButtonHoverGreen: "#5db761" + property string acceptButtonPressedGreen: "#449d48" + + property string declineButtonRed: "#f44336" + property string declineButtonHoverRed: "#f5554a" + property string declineButtonPressedRed: "#db3c30" + + property string hangUpButtonTintedRed: "#ff0000" + property string buttonTintedBlue: "#00aaff" + + property string selectionBlue: "#109ede" + property string selectionGreen: "#21be2b" + property string rubberBandSelectionBlue: "steelblue" + + property string closeButtonLighterBlack: "#4c4c4c" + + property string contactSearchBarPlaceHolderTextFontColor: "#767676" + property string contactSearchBarPlaceHolderGreyBackground: "#dddddd" + + property string draftRed: "#cf5300" + + + /* + * Font. + */ + property string faddedFontColor: "#c0c0c0" + property string faddedLastInteractionFontColor: "#505050" + + property int splitViewHandlePreferedWidth: 4 + property int textFontSize: 9 + + + /* + * Place holder text. + */ + property string contactSearchBarPlaceHolderConversationText: qsTr("Find or start a conversation") + property string contactSearchBarPlaceHolderInivitionText: qsTr("Search your received invitations") + + // Jami theme colors + function rgb256(r, g, b) { + return Qt.rgba(r / 256, g / 256, b / 256, 1) + } + + property color blue_: "#109ede" + property color lightBlue_: "#c1ebf0" + property color lightGrey_: rgb256(242, 242, 242) + property color imGrey_: "#dedee0" + property color imBlue_: "#cfebf5" + property color lightBlack_: rgb256(63, 63, 63) + property color grey_: rgb256(160, 160, 160) + property color red_: rgb256(251, 72, 71) + property color lightRed_: rgb256(252, 91, 90) + property color darkRed_: rgb256(219, 55, 54) + property color notificationRed_: rgb256(255, 59, 48) + property color urgentOrange_: rgb256(255, 165, 0) + property color green_: rgb256(127, 255, 0) + property color presenceGreen_: rgb256(76, 217, 100) + property color smartlistSelection_: rgb256(240, 240, 240) + property color smartlistHighlight_: rgb256(245, 245, 245) +} diff --git a/src/contactadapter.cpp b/src/contactadapter.cpp new file mode 100644 index 00000000..fb837aa4 --- /dev/null +++ b/src/contactadapter.cpp @@ -0,0 +1,180 @@ +/* + * Copyright (C) 2020 by Savoir-faire Linux + * Author: Edric Ladent Milaret + * Author: Andreas Traczyk + * Author: Mingrui Zhang + * + * 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 . + */ + +#include "contactadapter.h" + +#include "lrcinstance.h" + +ContactAdapter::ContactAdapter(QObject *parent) + : QmlAdapterBase(parent) +{ + selectableProxyModel_.reset(new SelectableProxyModel(smartListModel_.get())); +} + +ContactAdapter::~ContactAdapter() {} + +QVariant +ContactAdapter::getContactSelectableModel(int type) +{ + /* + * Called from qml every time contact picker refreshes. + */ + listModeltype_ = Utils::toEnum(type); + smartListModel_.reset(new SmartListModel(LRCInstance::getCurrAccId(), + this, + listModeltype_, + LRCInstance::getCurrentConvUid())); + selectableProxyModel_->setSourceModel(smartListModel_.get()); + + /* + * Adjust filter. + */ + switch (listModeltype_) { + case SmartListModel::Type::CONFERENCE: + selectableProxyModel_->setPredicate([this](const QModelIndex &index, const QRegExp &) { + return index.data(SmartListModel::Presence).toBool(); + }); + break; + case SmartListModel::Type::TRANSFER: + selectableProxyModel_->setPredicate([this](const QModelIndex &index, const QRegExp ®exp) { + /* + * Regex to remove current callee. + */ + QRegExp matchExcept = QRegExp(QString("\\b(?!" + calleeDisplayName_ + "\\b)\\w+")); + bool match = false; + bool match_non_self = matchExcept.indexIn( + index.data(SmartListModel::Role::DisplayName).toString()) + != -1; + if (match_non_self) { + match = regexp.indexIn(index.data(SmartListModel::Role::DisplayName).toString()) + != -1; + } + return match && !index.parent().isValid(); + }); + break; + default: + break; + } + selectableProxyModel_->invalidate(); + + return QVariant::fromValue(selectableProxyModel_.get()); +} + +void +ContactAdapter::setSearchFilter(const QString &filter) +{ + if (listModeltype_ == SmartListModel::Type::CONFERENCE) { + smartListModel_->setConferenceableFilter(filter); + } + selectableProxyModel_->setFilterRegExp( + QRegExp(filter, Qt::CaseInsensitive, QRegExp::FixedString)); +} + +void +ContactAdapter::contactSelected(int index) +{ + auto contactIndex = selectableProxyModel_->index(index, 0); + auto callModel = LRCInstance::getCurrentCallModel(); + auto conversation = LRCInstance::getCurrentConversation(); + + if (contactIndex.isValid()) { + switch (listModeltype_) { + case SmartListModel::Type::CONFERENCE: { + /* + * Conference. + */ + auto sectionName = contactIndex.data(SmartListModel::Role::SectionName).value(); + if (!sectionName.isEmpty()) { + smartListModel_->toggleSection(sectionName); + return; + } + + auto convUid = contactIndex.data(SmartListModel::Role::UID).value(); + auto accId = contactIndex.data(SmartListModel::Role::AccountId).value(); + auto callId = LRCInstance::getCallIdForConversationUid(convUid, accId); + + if (!callId.isEmpty()) { + if (conversation.uid.isEmpty()) { + return; + } + auto thisCallId = conversation.confId.isEmpty() ? conversation.callId + : conversation.confId; + + callModel->joinCalls(thisCallId, callId); + } else { + auto contactUri = contactIndex.data(SmartListModel::Role::URI).value(); + auto call = LRCInstance::getCallInfoForConversation(conversation); + if (!call) { + return; + } + callModel->callAndAddParticipant(contactUri, call->id, call->isAudioOnly); + } + } break; + case SmartListModel::Type::TRANSFER: { + /* + * SIP Transfer. + */ + auto contactUri = contactIndex.data(SmartListModel::Role::URI).value(); + + if (conversation.uid.isEmpty()) { + return; + } + auto callId = conversation.confId.isEmpty() ? conversation.callId : conversation.confId; + + QString destCallId; + + try { + /* + * Check if the call exist - (check non-finished calls). + */ + auto callInfo = callModel->getCallFromURI(contactUri, true); + destCallId = callInfo.id; + } catch (std::exception &e) { + qDebug().noquote() << e.what(); + destCallId = ""; + } + /* + * If no second call -> blind transfer. + * If there is a second call -> attended transfer. + */ + if (destCallId.size() == 0) { + callModel->transfer(callId, "sip:" + contactUri); + callModel->hangUp(callId); + } else { + callModel->transferToCall(callId, destCallId); + callModel->hangUp(callId); + callModel->hangUp(destCallId); + } + } break; + default: + break; + } + } +} + +void +ContactAdapter::setCalleeDisplayName(const QString &name) +{ + calleeDisplayName_ = name; +} + +void +ContactAdapter::initQmlObject() +{} diff --git a/src/contactadapter.h b/src/contactadapter.h new file mode 100644 index 00000000..4b694770 --- /dev/null +++ b/src/contactadapter.h @@ -0,0 +1,99 @@ +/* + * Copyright (C) 2020 by Savoir-faire Linux + * Author: Mingrui Zhang + * + * 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 . + */ + +#pragma once + +#include "qmladapterbase.h" +#include "smartlistmodel.h" + +#include +#include +#include + +/* + * The SelectableProxyModel class + * provides support for sorting and filtering data passed between another model and a view. + * + * User can customize a function pointer to pass to FilterPredicate to ensure which row in + * the source model can be accepted. + * + * Additionally, user need to setFilterRegExp to be able to get input QRegExp from FilterPredicate. + */ +class SelectableProxyModel : public QSortFilterProxyModel +{ +public: + using FilterPredicate = std::function; + + explicit SelectableProxyModel(QAbstractItemModel *parent) + : QSortFilterProxyModel(parent) + { + setSourceModel(parent); + } + ~SelectableProxyModel() {} + + void + setPredicate(FilterPredicate filterPredicate) + { + filterPredicate_ = filterPredicate; + } + + virtual bool + filterAcceptsRow(int source_row, const QModelIndex &source_parent) const + { + /* + * Accept all contacts in conversation list filtered with account type, except those in a call. + */ + auto index = sourceModel()->index(source_row, 0, source_parent); + if (filterPredicate_) { + return filterPredicate_(index, filterRegExp()); + } + } + +private: + std::function filterPredicate_; +}; + +class ContactAdapter : public QmlAdapterBase +{ + Q_OBJECT + +public: + explicit ContactAdapter(QObject *parent = nullptr); + ~ContactAdapter(); + + Q_INVOKABLE QVariant getContactSelectableModel(int type); + Q_INVOKABLE void setSearchFilter(const QString &filter); + Q_INVOKABLE void contactSelected(int index); + Q_INVOKABLE void setCalleeDisplayName(const QString &name); + +private: + void initQmlObject() override; + + SmartListModel::Type listModeltype_; + + /* + * For sip call transfer, to exclude current sip callee. + */ + QString calleeDisplayName_; + + /* + * SmartListModel is the source model of SelectableProxyModel. + */ + std::unique_ptr smartListModel_; + std::unique_ptr selectableProxyModel_; +}; diff --git a/src/conversationsadapter.cpp b/src/conversationsadapter.cpp new file mode 100644 index 00000000..d5cd4b5d --- /dev/null +++ b/src/conversationsadapter.cpp @@ -0,0 +1,304 @@ +/* + * Copyright (C) 2020 by Savoir-faire Linux + * Author: Edric Ladent Milaret + * Author: Anthony Lonard + * Author: Olivier Soldano + * Author: Andreas Traczyk + * Author: Isa Nanic + * Author: Mingrui Zhang + * + * 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 . + */ + +#include "conversationsadapter.h" + +#include "utils.h" + +ConversationsAdapter::ConversationsAdapter(QObject *parent) + : QmlAdapterBase(parent) +{} + +ConversationsAdapter::~ConversationsAdapter() {} + +void +ConversationsAdapter::initQmlObject() +{ + conversationSmartListModel_ = new SmartListModel(LRCInstance::getCurrAccId(), this); + + QMetaObject::invokeMethod(qmlObj_, + "setModel", + Q_ARG(QVariant, QVariant::fromValue(conversationSmartListModel_))); + + connect(&LRCInstance::behaviorController(), + &BehaviorController::showChatView, + [this](const QString &accountId, lrc::api::conversation::Info convInfo) { + emit showChatView(accountId, convInfo.uid); + }); + + connectConversationModel(); +} + +void +ConversationsAdapter::backToWelcomePage() +{ + deselectConversation(); + QMetaObject::invokeMethod(qmlObj_, "backToWelcomePage"); +} + +void +ConversationsAdapter::selectConversation(const QString &accountId, + const QString &convUid, + bool preventSendingSignal) +{ + selectConversation(LRCInstance::getConversationFromConvUid(convUid, accountId), + preventSendingSignal); +} + +void +ConversationsAdapter::selectConversation(int index) +{ + auto convModel = LRCInstance::getCurrentConversationModel(); + + if (convModel == nullptr) { + return; + } + + const auto item = convModel->filteredConversation(index); + + if (selectConversation(item, false)) { + auto convUid = conversationSmartListModel_ + ->data(conversationSmartListModel_->index(index, 0), + static_cast(SmartListModel::Role::UID)) + .toString(); + auto &conversation = LRCInstance::getConversationFromConvUid(convUid); + /* + * If it is calling, show callview (can use showChatView signal, since it will be determined on qml). + */ + if (!conversation.uid.isEmpty() + && LRCInstance::getCurrentCallModel()->hasCall(conversation.callId)) { + emit showChatView(LRCInstance::getCurrAccId(), conversation.uid); + } + } +} + +bool +ConversationsAdapter::selectConversation(const lrc::api::conversation::Info &item, + bool preventSendingSignal) +{ + /* + * accInfo.conversationModel->selectConversation(item.uid) only emit ui + * behavior control signals, but sometimes we do not want that, + * preventSendingSignal boolean can help us to determine. + */ + if (LRCInstance::getCurrentConvUid() == item.uid) { + return false; + } else if (item.participants.size() > 0) { + auto &accInfo = LRCInstance::getAccountInfo(item.accountId); + LRCInstance::setSelectedConvId(item.uid); + if (!preventSendingSignal) + accInfo.conversationModel->selectConversation(item.uid); + accInfo.conversationModel->clearUnreadInteractions(item.uid); + return true; + } +} + +void +ConversationsAdapter::deselectConversation() +{ + if (LRCInstance::getCurrentConvUid().isEmpty()) { + return; + } + + auto currentConversationModel = LRCInstance::getCurrentConversationModel(); + + if (currentConversationModel == nullptr) { + return; + } + + currentConversationModel->selectConversation(""); + LRCInstance::setSelectedConvId(); +} + +void +ConversationsAdapter::accountChangedSetUp(const QString &accountId) +{ + /* + * Should be called when current account is changed. + */ + auto &accountInfo = LRCInstance::accountModel().getAccountInfo(accountId); + currentTypeFilter_ = accountInfo.profileInfo.type; + LRCInstance::getCurrentConversationModel()->setFilter(accountInfo.profileInfo.type); + updateConversationsFilterWidget(); + + connectConversationModel(); +} + +void +ConversationsAdapter::updateConversationsFilterWidget() +{ + /* + * Update status of "Conversations" and "Invitations". + */ + auto invites = LRCInstance::getCurrentAccountInfo().contactModel->pendingRequestCount(); + if (invites == 0 && currentTypeFilter_ == lrc::api::profile::Type::PENDING) { + currentTypeFilter_ = lrc::api::profile::Type::RING; + LRCInstance::getCurrentConversationModel()->setFilter(currentTypeFilter_); + } + showConversationTabs(invites); +} + +void +ConversationsAdapter::setConversationFilter(const QString &type) +{ + /* + * Set conversation filter according to type, + * type needs to be recognizable by lrc::api::profile::to_type. + */ + if (type.isEmpty()) { + if (LRCInstance::getCurrentAccountInfo().profileInfo.type == lrc::api::profile::Type::RING) + setConversationFilter(lrc::api::profile::Type::RING); + else + setConversationFilter(lrc::api::profile::Type::SIP); + } else { + setConversationFilter(lrc::api::profile::to_type(type)); + } +} + +void +ConversationsAdapter::setConversationFilter(lrc::api::profile::Type filter) +{ + if (currentTypeFilter_ == filter) { + return; + } + currentTypeFilter_ = filter; + LRCInstance::getCurrentConversationModel()->setFilter(currentTypeFilter_); +} + +bool +ConversationsAdapter::connectConversationModel() +{ + /* + * Signal connections + */ + auto currentConversationModel = LRCInstance::getCurrentAccountInfo().conversationModel.get(); + + QObject::disconnect(modelSortedConnection_); + QObject::disconnect(modelUpdatedConnection_); + QObject::disconnect(filterChangedConnection_); + QObject::disconnect(newConversationConnection_); + QObject::disconnect(conversationRemovedConnection_); + QObject::disconnect(conversationClearedConnection); + QObject::disconnect(newInteractionConnection_); + QObject::disconnect(interactionRemovedConnection_); + + modelSortedConnection_ = QObject::connect( + currentConversationModel, &lrc::api::ConversationModel::modelSorted, [this]() { + updateConversationsFilterWidget(); + QMetaObject::invokeMethod(qmlObj_, "updateConversationSmartListView"); + auto convUid = LRCInstance::getCurrentConversation().uid; + auto convModel = LRCInstance::getCurrentConversationModel(); + auto &conversation = LRCInstance::getConversationFromConvUid(convUid); + if (conversation.uid.isEmpty()) { + return; + } + auto contactURI = conversation.participants[0]; + if (contactURI.isEmpty() + || convModel->owner.contactModel->getContact(contactURI).profileInfo.type + == lrc::api::profile::Type::TEMPORARY) { + return; + } + QMetaObject::invokeMethod(qmlObj_, "modelSorted", Q_ARG(QVariant, contactURI)); + }); + + modelUpdatedConnection_ + = QObject::connect(currentConversationModel, + &lrc::api::ConversationModel::conversationUpdated, + [this](const QString &convUid) { + Q_UNUSED(convUid); + updateConversationsFilterWidget(); + QMetaObject::invokeMethod(qmlObj_, "updateConversationSmartListView"); + }); + + filterChangedConnection_ = QObject::connect( + currentConversationModel, &lrc::api::ConversationModel::filterChanged, [this]() { + QMetaObject::invokeMethod(qmlObj_, + "updateSmartList", + Q_ARG(QVariant, LRCInstance::getCurrAccId())); + updateConversationsFilterWidget(); + QMetaObject::invokeMethod(qmlObj_, "updateConversationSmartListView"); + }); + + newConversationConnection_ + = QObject::connect(currentConversationModel, + &lrc::api::ConversationModel::newConversation, + [this](const QString &convUid) { + QMetaObject::invokeMethod(qmlObj_, + "updateSmartList", + Q_ARG(QVariant, + LRCInstance::getCurrAccId())); + updateConversationForNewContact(convUid); + }); + + conversationRemovedConnection_ + = QObject::connect(currentConversationModel, + &lrc::api::ConversationModel::conversationRemoved, + [this]() { backToWelcomePage(); }); + + conversationClearedConnection + = QObject::connect(currentConversationModel, + &lrc::api::ConversationModel::conversationCleared, + [this](const QString &convUid) { + /* + * If currently selected, + * switch to welcome screen (deselecting current smartlist item ). + */ + if (convUid != LRCInstance::getCurrentConvUid()) { + return; + } + backToWelcomePage(); + }); + + newInteractionConnection_ + = QObject::connect(currentConversationModel, + &lrc::api::ConversationModel::newInteraction, + [this] { + updateConversationsFilterWidget(); + QMetaObject::invokeMethod(qmlObj_, "updateConversationSmartListView"); + }); + + currentConversationModel->setFilter(""); + return true; +} + +void +ConversationsAdapter::updateConversationForNewContact(const QString &convUid) +{ + auto convModel = LRCInstance::getCurrentConversationModel(); + if (convModel == nullptr) { + return; + } + auto selectedUid = LRCInstance::getCurrentConvUid(); + auto &conversation = LRCInstance::getConversationFromConvUid(convUid, {}, true); + if (!conversation.uid.isEmpty()) { + try { + auto contact = convModel->owner.contactModel->getContact(conversation.participants[0]); + if (!contact.profileInfo.uri.isEmpty() && contact.profileInfo.uri == selectedUid) { + LRCInstance::setSelectedConvId(convUid); + convModel->selectConversation(convUid); + } + } catch (...) { + return; + } + } +} \ No newline at end of file diff --git a/src/conversationsadapter.h b/src/conversationsadapter.h new file mode 100644 index 00000000..33dea8fc --- /dev/null +++ b/src/conversationsadapter.h @@ -0,0 +1,75 @@ +/* + * Copyright (C) 2020 by Savoir-faire Linux + * Author: Mingrui Zhang + * + * 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 . + */ + +#pragma once + +#include "lrcinstance.h" +#include "qmladapterbase.h" +#include "smartlistmodel.h" + +#include +#include + +class ConversationsAdapter : public QmlAdapterBase +{ + Q_OBJECT + +public: + explicit ConversationsAdapter(QObject *parent = nullptr); + ~ConversationsAdapter(); + + Q_INVOKABLE bool connectConversationModel(); + Q_INVOKABLE void selectConversation(const QString &accountId, + const QString &convUid, + bool preventSendingSignal = true); + Q_INVOKABLE void selectConversation(int index); + Q_INVOKABLE void deselectConversation(); + Q_INVOKABLE void accountChangedSetUp(const QString &accountId); + Q_INVOKABLE void updateConversationsFilterWidget(); + Q_INVOKABLE void setConversationFilter(const QString &type); + +signals: + void showChatView(const QString &accountId, const QString &convUid); + void showConversationTabs(bool visible); + +private: + void initQmlObject() override; + void setConversationFilter(lrc::api::profile::Type filter); + void backToWelcomePage(); + bool selectConversation(const lrc::api::conversation::Info &item, + bool preventSendingSignal = true); + void updateConversationForNewContact(const QString &convUid); + + SmartListModel *conversationSmartListModel_; + + lrc::api::profile::Type currentTypeFilter_{}; + + /* + * Connections. + */ + QMetaObject::Connection modelSortedConnection_; + QMetaObject::Connection modelUpdatedConnection_; + QMetaObject::Connection filterChangedConnection_; + QMetaObject::Connection newConversationConnection_; + QMetaObject::Connection conversationRemovedConnection_; + QMetaObject::Connection newInteractionConnection_; + QMetaObject::Connection conversationClearedConnection; + QMetaObject::Connection selectedCallChanged_; + QMetaObject::Connection smartlistSelectionConnection_; + QMetaObject::Connection interactionRemovedConnection_; +}; diff --git a/src/deviceitemlistmodel.cpp b/src/deviceitemlistmodel.cpp new file mode 100644 index 00000000..6b2739c0 --- /dev/null +++ b/src/deviceitemlistmodel.cpp @@ -0,0 +1,117 @@ +/* + * Copyright (C) 2019-2020 by Savoir-faire Linux + * Author: Yang Wang + * + * 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 . + */ + +#include "deviceitemlistmodel.h" + +DeviceItemListModel::DeviceItemListModel(QObject *parent) + : QAbstractListModel(parent) +{} + +DeviceItemListModel::~DeviceItemListModel() {} + +int +DeviceItemListModel::rowCount(const QModelIndex &parent) const +{ + if (!parent.isValid()) { + /* + * Count. + */ + return LRCInstance::getCurrentAccountInfo().deviceModel->getAllDevices().size(); + } + /* + * A valid QModelIndex returns 0 as no entry has sub-elements. + */ + return 0; +} + +int +DeviceItemListModel::columnCount(const QModelIndex &parent) const +{ + Q_UNUSED(parent); + /* + * Only need one column. + */ + return 1; +} + +QVariant +DeviceItemListModel::data(const QModelIndex &index, int role) const +{ + auto deviceList = LRCInstance::getCurrentAccountInfo().deviceModel->getAllDevices(); + if (!index.isValid() || deviceList.size() <= index.row()) { + return QVariant(); + } + + switch (role) { + case Role::DeviceName: + return QVariant(deviceList.at(index.row()).name); + case Role::DeviceID: + return QVariant(deviceList.at(index.row()).id); + case Role::IsCurrent: + return QVariant(deviceList.at(index.row()).isCurrent); + } + return QVariant(); +} + +QHash +DeviceItemListModel::roleNames() const +{ + QHash roles; + roles[DeviceName] = "DeviceName"; + roles[DeviceID] = "DeviceID"; + roles[IsCurrent] = "IsCurrent"; + return roles; +} + +QModelIndex +DeviceItemListModel::index(int row, int column, const QModelIndex &parent) const +{ + Q_UNUSED(parent); + if (column != 0) { + return QModelIndex(); + } + + if (row >= 0 && row < rowCount()) { + return createIndex(row, column); + } + return QModelIndex(); +} + +QModelIndex +DeviceItemListModel::parent(const QModelIndex &child) const +{ + Q_UNUSED(child); + return QModelIndex(); +} + +Qt::ItemFlags +DeviceItemListModel::flags(const QModelIndex &index) const +{ + auto flags = QAbstractItemModel::flags(index) | Qt::ItemNeverHasChildren | Qt::ItemIsSelectable; + if (!index.isValid()) { + return QAbstractItemModel::flags(index); + } + return flags; +} + +void +DeviceItemListModel::reset() +{ + beginResetModel(); + endResetModel(); +} diff --git a/src/deviceitemlistmodel.h b/src/deviceitemlistmodel.h new file mode 100644 index 00000000..ff560710 --- /dev/null +++ b/src/deviceitemlistmodel.h @@ -0,0 +1,59 @@ +/* + * Copyright (C) 2019-2020 by Savoir-faire Linux + * Author: Yang Wang + * + * 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 . + */ + +#pragma once + +#include + +#include "api/account.h" +#include "api/contact.h" +#include "api/conversation.h" +#include "api/newdevicemodel.h" + +#include "lrcinstance.h" + +class DeviceItemListModel : public QAbstractListModel +{ + Q_OBJECT + +public: + enum Role { DeviceName = Qt::UserRole + 1, DeviceID, IsCurrent }; + Q_ENUM(Role) + + explicit DeviceItemListModel(QObject *parent = 0); + ~DeviceItemListModel(); + + /* + * QAbstractListModel override. + */ + int rowCount(const QModelIndex &parent = QModelIndex()) const override; + int columnCount(const QModelIndex &parent) const override; + QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override; + /* + * Override role name as access point in qml. + */ + QHash roleNames() const override; + QModelIndex index(int row, int column = 0, const QModelIndex &parent = QModelIndex()) const; + QModelIndex parent(const QModelIndex &child) const; + Qt::ItemFlags flags(const QModelIndex &index) const; + + /* + * This function is to reset the model when there's new account added. + */ + Q_INVOKABLE void reset(); +}; diff --git a/src/distantrenderer.cpp b/src/distantrenderer.cpp new file mode 100644 index 00000000..023442b3 --- /dev/null +++ b/src/distantrenderer.cpp @@ -0,0 +1,65 @@ +/* + * Copyright (C) 2019-2020 by Savoir-faire Linux + * Author: Andreas Traczyk + * Author: Mingrui Zhang + * + * 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 . + */ + +#include "distantrenderer.h" + +#include "lrcinstance.h" + +DistantRenderer::DistantRenderer(QQuickItem *parent) + : QQuickPaintedItem(parent) +{ + setAntialiasing(true); + setFillColor(Qt::black); + setRenderTarget(QQuickPaintedItem::FramebufferObject); + setPerformanceHint(QQuickPaintedItem::FastFBOResizing); + + connect(LRCInstance::renderer(), &RenderManager::distantFrameUpdated, [this](const QString &id) { + if (distantRenderId_ == id) + update(QRect(0, 0, width(), height())); + }); + + connect(LRCInstance::renderer(), + &RenderManager::distantRenderingStopped, + [this](const QString &id) { + if (distantRenderId_ == id) + update(QRect(0, 0, width(), height())); + }); +} + +DistantRenderer::~DistantRenderer() {} + +void +DistantRenderer::setRendererId(const QString &id) +{ + distantRenderId_ = id; + update(QRect(0, 0, width(), height())); +} + +void +DistantRenderer::paint(QPainter *painter) +{ + auto distantImage = LRCInstance::renderer()->getFrame(distantRenderId_); + if (distantImage) { + auto scaledDistant = distantImage->scaled(size().toSize(), Qt::KeepAspectRatio); + auto xDiff = (width() - scaledDistant.width()) / 2; + auto yDiff = (height() - scaledDistant.height()) / 2; + painter->drawImage(QRect(xDiff, yDiff, scaledDistant.width(), scaledDistant.height()), + scaledDistant); + } +} \ No newline at end of file diff --git a/src/distantrenderer.h b/src/distantrenderer.h new file mode 100644 index 00000000..d26f2c2c --- /dev/null +++ b/src/distantrenderer.h @@ -0,0 +1,45 @@ +/* + * Copyright (C) 2020 by Savoir-faire Linux + * Author: Andreas Traczyk + * Author: Mingrui Zhang + * + * 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 . + */ + +#pragma once + +#include + +/* + * Use QQuickPaintedItem so that QPainter apis can be used. + * Note: Old video pipeline. + */ + +class DistantRenderer : public QQuickPaintedItem +{ + Q_OBJECT +public: + explicit DistantRenderer(QQuickItem *parent = 0); + ~DistantRenderer(); + + Q_INVOKABLE void setRendererId(const QString &id); + +private: + void paint(QPainter *painter); + + /* + * Unique DistantRenderId for each call. + */ + QString distantRenderId_; +}; \ No newline at end of file diff --git a/src/globalsystemtray.cpp b/src/globalsystemtray.cpp new file mode 100644 index 00000000..a1271c5e --- /dev/null +++ b/src/globalsystemtray.cpp @@ -0,0 +1,45 @@ +/* + * Copyright (C) 2015-2020 by Savoir-faire Linux + * Author: Edric Ladent Milaret + * + * 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 . + */ + +#include "globalsystemtray.h" + +GlobalSystemTray::GlobalSystemTray() {} + +void +GlobalSystemTray::setTriggeredAccountId(const QString &accountId) +{ + triggeredAccountId_ = accountId; +} + +const QString & +GlobalSystemTray::getTriggeredAccountId() +{ + return triggeredAccountId_; +} + +void +GlobalSystemTray::setPossibleOnGoingConversationInfo(const lrc::api::conversation::Info &convInfo) +{ + triggeredOnGoingConvInfo_ = convInfo; +} + +const lrc::api::conversation::Info & +GlobalSystemTray::getPossibleOnGoingConversationInfo() +{ + return triggeredOnGoingConvInfo_; +} diff --git a/src/globalsystemtray.h b/src/globalsystemtray.h new file mode 100644 index 00000000..e72713cb --- /dev/null +++ b/src/globalsystemtray.h @@ -0,0 +1,55 @@ +/* + * Copyright (C) 2015-2020 by Savoir-faire Linux + * Author: Edric Ladent Milaret + * + * 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 . + */ + +#pragma once + +#include "lrcinstance.h" + +#include + +class GlobalSystemTray : public QSystemTrayIcon +{ + Q_OBJECT + +public: + static GlobalSystemTray & + instance() + { + static GlobalSystemTray *instance_ = new GlobalSystemTray(); + + return *instance_; + } + + /* + * Remember the last triggering account for the notification, + * safe since user cannot activate previous notifications. + */ + void setTriggeredAccountId(const QString &accountId); + + const QString &getTriggeredAccountId(); + + void setPossibleOnGoingConversationInfo(const lrc::api::conversation::Info &convInfo); + + const lrc::api::conversation::Info &getPossibleOnGoingConversationInfo(); + +private: + GlobalSystemTray(); + + QString triggeredAccountId_; + lrc::api::conversation::Info triggeredOnGoingConvInfo_; +}; diff --git a/src/jamiavatartheme.h b/src/jamiavatartheme.h new file mode 100644 index 00000000..08e721a1 --- /dev/null +++ b/src/jamiavatartheme.h @@ -0,0 +1,43 @@ +/* + * Copyright (C) 2017-2020 by Savoir-faire Linux + * Author: Edric Ladent Milaret + * + * 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 . + */ + +#include + +#pragma once + +namespace JamiAvatarTheme { +static const QColor defaultAvatarColor_ = {"#ff9e9e9e"}; //Grey +static const QColor avatarColors_[]{ + {"#fff44336"}, //Red + {"#ffe91e63"}, //Pink + {"#ff9c27b0"}, //Purple + {"#ff673ab7"}, //Deep Purple + {"#ff3f51b5"}, //Indigo + {"#ff2196f3"}, //Blue + {"#ff00bcd4"}, //Cyan + {"#ff009688"}, //Teal + {"#ff4caf50"}, //Green + {"#ff8bc34a"}, //Light Green + {"#ff9e9e9e"}, //Grey + {"#ffcddc39"}, //Lime + {"#ffffc107"}, //Amber + {"#ffff5722"}, //Deep Orange + {"#ff795548"}, //Brown + {"#ff607d8b"} //Blue Grey +}; +} // namespace JamiAvatarTheme diff --git a/src/lrcinstance.h b/src/lrcinstance.h new file mode 100644 index 00000000..16762f14 --- /dev/null +++ b/src/lrcinstance.h @@ -0,0 +1,475 @@ +/* + * Copyright (C) 2019-2020 by Savoir-faire Linux + * Author: Andreas Traczyk + * Author: Isa Nanic + * Author: Mingrui Zhang + * + * 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 . + */ + +#pragma once + +#ifdef _MSC_VER +#undef ERROR +#endif + +#include "accountlistmodel.h" +#include "rendermanager.h" +#include "settingskey.h" +#include "utils.h" + +#include "api/account.h" +#include "api/avmodel.h" +#include "api/pluginmodel.h" +#include "api/behaviorcontroller.h" +#include "api/contact.h" +#include "api/contactmodel.h" +#include "api/conversation.h" +#include "api/conversationmodel.h" +#include "api/datatransfermodel.h" +#include "api/lrc.h" +#include "api/newaccountmodel.h" +#include "api/newcallmodel.h" +#include "api/newcodecmodel.h" +#include "api/newdevicemodel.h" +#include "api/peerdiscoverymodel.h" + +#include +#include +#include +#include +#include +#include +#include + +#include + +using namespace lrc::api; + +using migrateCallback = std::function; +using getConvPredicate = std::function; + +class LRCInstance : public QObject +{ + Q_OBJECT + +public: + static LRCInstance & + instance(migrateCallback willMigrate = {}, migrateCallback didMigrate = {}) + { + static LRCInstance instance_(willMigrate, didMigrate); + return instance_; + }; + static void + init(migrateCallback willMigrate = {}, migrateCallback didMigrate = {}) + { + instance(willMigrate, didMigrate); + }; + static Lrc & + getAPI() + { + return *(instance().lrc_); + }; + static RenderManager * + renderer() + { + return instance().renderer_.get(); + } + static void + connectivityChanged() + { + instance().lrc_->connectivityChanged(); + }; + static NewAccountModel & + accountModel() + { + return instance().lrc_->getAccountModel(); + }; + static BehaviorController & + behaviorController() + { + return instance().lrc_->getBehaviorController(); + }; + static DataTransferModel & + dataTransferModel() + { + return instance().lrc_->getDataTransferModel(); + }; + static AVModel & + avModel() + { + return instance().lrc_->getAVModel(); + }; + static PluginModel & + pluginModel() + { + return instance().lrc_->getPluginModel(); + }; + static bool + isConnected() + { + return instance().lrc_->isConnected(); + }; + static VectorString + getActiveCalls() + { + return instance().lrc_->activeCalls(); + }; + static const account::Info & + getAccountInfo(const QString &accountId) + { + return accountModel().getAccountInfo(accountId); + }; + static const account::Info & + getCurrentAccountInfo() + { + return getAccountInfo(getCurrAccId()); + }; + static bool + hasVideoCall() + { + auto activeCalls = instance().lrc_->activeCalls(); + auto accountList = accountModel().getAccountList(); + bool result = false; + for (const auto &callId : activeCalls) { + for (const auto &accountId : accountList) { + auto &accountInfo = accountModel().getAccountInfo(accountId); + if (accountInfo.callModel->hasCall(callId)) { + auto call = accountInfo.callModel->getCall(callId); + result |= !(call.isAudioOnly || call.videoMuted); + } + } + } + return result; + }; + static QString + getCallIdForConversationUid(const QString &convUid, const QString &accountId) + { + auto convInfo = LRCInstance::getConversationFromConvUid(convUid, accountId); + if (convInfo.uid.isEmpty()) { + return {}; + } + return convInfo.confId.isEmpty() ? convInfo.callId : convInfo.confId; + } + static const call::Info * + getCallInfo(const QString &callId, const QString &accountId) + { + try { + auto &accInfo = LRCInstance::accountModel().getAccountInfo(accountId); + if (!accInfo.callModel->hasCall(callId)) { + return nullptr; + } + return &accInfo.callModel->getCall(callId); + } catch (...) { + return nullptr; + } + } + static const call::Info * + getCallInfoForConversation(const conversation::Info &convInfo, bool forceCallOnly = {}) + { + try { + auto accountId = convInfo.accountId; + auto &accInfo = LRCInstance::accountModel().getAccountInfo(accountId); + auto callId = forceCallOnly + ? convInfo.callId + : (convInfo.confId.isEmpty() ? convInfo.callId : convInfo.confId); + if (!accInfo.callModel->hasCall(callId)) { + return nullptr; + } + return &accInfo.callModel->getCall(callId); + } catch (...) { + return nullptr; + } + } + static const conversation::Info & + getConversation(const QString &accountId, getConvPredicate pred = {}, bool filtered = false) + { + using namespace lrc::api; + static conversation::Info invalid = {}; + try { + auto &accInfo = LRCInstance::getAccountInfo(accountId); + auto &convModel = accInfo.conversationModel; + if (filtered) { + auto &convs = convModel->allFilteredConversations(); + auto conv = std::find_if(convs.begin(), convs.end(), pred); + if (conv != convs.end()) { + return *conv; + } + } else { + for (int i = Utils::toUnderlyingValue(profile::Type::RING); + i <= Utils::toUnderlyingValue(profile::Type::TEMPORARY); + ++i) { + auto filter = Utils::toEnum(i); + auto &convs = convModel->getFilteredConversations(filter); + auto conv = std::find_if(convs.begin(), convs.end(), pred); + if (conv != convs.end()) { + return *conv; + } + } + } + } catch (...) { + } + return invalid; + } + static const conversation::Info & + getConversationFromCallId(const QString &callId, + const QString &accountId = {}, + bool filtered = false) + { + return getConversation( + !accountId.isEmpty() ? accountId : getCurrAccId(), + [&](const conversation::Info &conv) -> bool { return callId == conv.callId; }, + filtered); + } + static const conversation::Info & + getConversationFromConvUid(const QString &convUid, + const QString &accountId = {}, + bool filtered = false) + { + return getConversation( + !accountId.isEmpty() ? accountId : getCurrAccId(), + [&](const conversation::Info &conv) -> bool { return convUid == conv.uid; }, + filtered); + } + static const conversation::Info & + getConversationFromPeerUri(const QString &peerUri, + const QString &accountId = {}, + bool filtered = false) + { + return getConversation( + !accountId.isEmpty() ? accountId : getCurrAccId(), + [&](const conversation::Info &conv) -> bool { return peerUri == conv.participants[0]; }, + filtered); + } + static const conversation::Info & + getCurrentConversation() + { + return getConversationFromConvUid(getCurrentConvUid()); + } + + static ConversationModel * + getCurrentConversationModel() + { + return getCurrentAccountInfo().conversationModel.get(); + }; + + static NewCallModel * + getCurrentCallModel() + { + return getCurrentAccountInfo().callModel.get(); + }; + + static const QString & + getCurrAccId() + { + auto accountList = accountModel().getAccountList(); + if (instance().selectedAccountId_.isEmpty() && accountList.size()) { + instance().selectedAccountId_ = accountList.at(0); + } + return instance().selectedAccountId_; + }; + + static void + setSelectedAccountId(const QString &accountId = {}) + { + instance().selectedAccountId_ = accountId; + QSettings settings("jami.net", "Jami"); + settings.setValue(SettingsKey::selectedAccount, accountId); + + // Last selected account should be set as preferred. + accountModel().setTopAccount(accountId); + }; + + static const QString & + getCurrentConvUid() + { + return instance().selectedConvUid_; + }; + + static void + setSelectedConvId(const QString &convUid = {}) + { + instance().selectedConvUid_ = convUid; + }; + + static void + reset(bool newInstance = false) + { + if (newInstance) { + instance().renderer_.reset(new RenderManager(avModel())); + instance().lrc_.reset(new Lrc()); + } else { + instance().renderer_.reset(); + instance().lrc_.reset(); + } + }; + + static const int + getCurrentAccountIndex() + { + for (int i = 0; i < accountModel().getAccountList().size(); i++) { + if (accountModel().getAccountList()[i] == getCurrAccId()) { + return i; + } + } + return -1; + }; + + static const QPixmap + getCurrAccPixmap() + { + return instance() + .accountListModel_ + .data(instance().accountListModel_.index(getCurrentAccountIndex()), + AccountListModel::Role::Picture) + .value(); + }; + + static void + setAvatarForAccount(const QPixmap &avatarPixmap, const QString &accountID) + { + QByteArray ba; + QBuffer bu(&ba); + bu.open(QIODevice::WriteOnly); + avatarPixmap.save(&bu, "PNG"); + auto str = QString::fromLocal8Bit(ba.toBase64()); + accountModel().setAvatar(accountID, str); + }; + + static void + setCurrAccAvatar(const QPixmap &avatarPixmap) + { + QByteArray ba; + QBuffer bu(&ba); + bu.open(QIODevice::WriteOnly); + avatarPixmap.save(&bu, "PNG"); + auto str = QString::fromLocal8Bit(ba.toBase64()); + accountModel().setAvatar(getCurrAccId(), str); + }; + + static void + setCurrAccAvatar(const QString &avatar) + { + accountModel().setAvatar(getCurrAccId(), avatar); + }; + + static void + setCurrAccDisplayName(const QString &displayName) + { + auto accountId = LRCInstance::getCurrAccId(); + accountModel().setAlias(accountId, displayName); + /* + * Force save to .yml. + */ + auto confProps = LRCInstance::accountModel().getAccountConfig(accountId); + LRCInstance::accountModel().setAccountConfig(accountId, confProps); + }; + + static const account::ConfProperties_t & + getCurrAccConfig() + { + return instance().getCurrentAccountInfo().confProperties; + } + + static void + subscribeToDebugReceived() + { + instance().lrc_->subscribeToDebugReceived(); + } + + static void + startAudioMeter(bool async) + { + auto f = [] { + if (!LRCInstance::getActiveCalls().size()) { + LRCInstance::avModel().startAudioDevice(); + } + LRCInstance::avModel().setAudioMeterState(true); + }; + if (async) { + QtConcurrent::run(f); + } else { + f(); + } + } + + static void + stopAudioMeter(bool async) + { + auto f = [] { + if (!LRCInstance::getActiveCalls().size()) { + LRCInstance::avModel().stopAudioDevice(); + } + LRCInstance::avModel().setAudioMeterState(false); + }; + if (async) { + QtConcurrent::run(f); + } else { + f(); + } + } + + static QString + getContentDraft(const QString &convUid, const QString &accountId) + { + auto draftKey = accountId + "_" + convUid; + return instance().contentDrafts_[draftKey]; + } + + static void + setContentDraft(const QString &convUid, const QString &accountId, const QString &content) + { + auto draftKey = accountId + "_" + convUid; + instance().contentDrafts_[draftKey] = content; + } + + static void + pushLastConferencee(const QString &confId, const QString &callId) + { + instance().lastConferencees_[confId] = callId; + } + + static QString + popLastConferencee(const QString &confId) + { + QString callId = {}; + auto iter = instance().lastConferencees_.find(confId); + if (iter != instance().lastConferencees_.end()) { + callId = iter.value(); + instance().lastConferencees_.erase(iter); + } + return callId; + } + +signals: + void accountListChanged(); + +private: + LRCInstance(migrateCallback willMigrateCb = {}, migrateCallback didMigrateCb = {}) + { + lrc_ = std::make_unique(willMigrateCb, didMigrateCb); + renderer_ = std::make_unique(lrc_->getAVModel()); + }; + + std::unique_ptr lrc_; + std::unique_ptr renderer_; + AccountListModel accountListModel_; + QString selectedAccountId_; + QString selectedConvUid_; + MapStringString contentDrafts_; + MapStringString lastConferencees_; +}; +#if QT_VERSION >= QT_VERSION_CHECK(5, 8, 0) +Q_DECLARE_METATYPE(LRCInstance *) +#endif diff --git a/src/main.cpp b/src/main.cpp new file mode 100644 index 00000000..2b1349ce --- /dev/null +++ b/src/main.cpp @@ -0,0 +1,72 @@ +/* + * Copyright (C) 2015-2020 by Savoir-faire Linux + * Author: Edric Ladent Milaret + * Author: Andreas Traczyk + * Author: Mingrui Zhang + * + * 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 . + */ + +#include "mainapplication.h" +#include "runguard.h" + +#include +#include + +#include + +int +main(int argc, char *argv[]) +{ + setlocale(LC_ALL, "en_US.utf8"); +#ifdef Q_OS_LINUX + setenv("QT_QPA_PLATFORMTHEME", "gtk3", true); +#endif + + MainApplication::applicationInitialization(); + + char ARG_DISABLE_WEB_SECURITY[] = "--disable-web-security"; + auto newArgv = MainApplication::parseInputArgument(argc, argv, ARG_DISABLE_WEB_SECURITY); + + MainApplication a(argc, newArgv); + + /* + * Runguard to make sure that only one instance runs at a time. + * Note: needs to be after the creation of the application + */ + QCryptographicHash appData(QCryptographicHash::Sha256); + appData.addData(QApplication::applicationName().toUtf8()); + appData.addData(QApplication::organizationDomain().toUtf8()); + RunGuard guard(appData.result()); + if (!guard.tryToRun()) { + /* + * No need to exitApp since app is not set up. + */ + return 0; + } + + if (!a.applicationSetup()) { + guard.release(); + a.exitApp(); + return 0; + } + + /* + * Exec the application. + */ + auto ret = a.exec(); + + guard.release(); + return ret; +} diff --git a/src/mainapplication.cpp b/src/mainapplication.cpp new file mode 100644 index 00000000..938a0eb5 --- /dev/null +++ b/src/mainapplication.cpp @@ -0,0 +1,450 @@ +/* + * Copyright (C) 2015-2020 by Savoir-faire Linux + * Author: Edric Ladent Milaret + * Author: Andreas Traczyk + * Author: Mingrui Zhang + * + * 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 . + */ + +#include "mainapplication.h" + +#include "accountadapter.h" +#include "accountlistmodel.h" +#include "accountstomigratelistmodel.h" +#include "audiocodeclistmodel.h" +#include "audioinputdevicemodel.h" +#include "audiomanagerlistmodel.h" +#include "audiooutputdevicemodel.h" +#include "avadapter.h" +#include "bannedlistmodel.h" +#include "calladapter.h" +#include "clientwrapper.h" +#include "contactadapter.h" +#include "conversationsadapter.h" +#include "deviceitemlistmodel.h" +#include "pluginitemlistmodel.h" +#include "preferenceitemlistmodel.h" +#include "distantrenderer.h" +#include "globalinstances.h" +#include "globalsystemtray.h" +#include "messagesadapter.h" +#include "namedirectory.h" +#include "pixbufmanipulator.h" +#include "previewrenderer.h" +#include "qrimageprovider.h" +#include "settingsadaptor.h" +#include "tintedbuttonimageprovider.h" +#include "utils.h" +#include "version.h" +#include "videocodeclistmodel.h" +#include "videoformatfpsmodel.h" +#include "videoformatresolutionmodel.h" +#include "videoinputdevicemodel.h" + +#include +#include +#include + +#include + +#ifdef Q_OS_WIN +#include +#endif + +#if defined _MSC_VER && !COMPILE_ONLY +#include +#endif + +MainApplication::MainApplication(int &argc, char **argv) + : QApplication(argc, argv) + , engine_(new QQmlApplicationEngine()) +{ + QObject::connect(this, &QApplication::aboutToQuit, [this] { exitApp(); }); +} + +void +MainApplication::applicationInitialization() +{ + /* + * Some attributes are needed to be set before the creation of the application. + */ + QApplication::setApplicationName("Ring"); + QApplication::setOrganizationDomain("jami.net"); + QApplication::setAttribute(Qt::AA_EnableHighDpiScaling, true); + QApplication::setAttribute(Qt::AA_UseHighDpiPixmaps); + QApplication::setQuitOnLastWindowClosed(false); + QCoreApplication::setAttribute(Qt::AA_UseOpenGLES); +#if QT_VERSION >= QT_VERSION_CHECK(5, 14, 0) + QApplication::setHighDpiScaleFactorRoundingPolicy( + Qt::HighDpiScaleFactorRoundingPolicy::RoundPreferFloor); + /* + * Initialize QtWebEngine. + */ + QtWebEngine::initialize(); +#endif +} + +void +MainApplication::consoleDebug() +{ +#ifdef Q_OS_WIN + AllocConsole(); + SetConsoleCP(CP_UTF8); + + freopen("CONOUT$", "w", stdout); + freopen("CONOUT$", "w", stderr); + + COORD coordInfo; + coordInfo.X = 130; + coordInfo.Y = 9000; + + SetConsoleScreenBufferSize(GetStdHandle(STD_OUTPUT_HANDLE), coordInfo); + SetConsoleMode(GetStdHandle(STD_OUTPUT_HANDLE), ENABLE_QUICK_EDIT_MODE | ENABLE_EXTENDED_FLAGS); +#endif +} + +void +MainApplication::vsConsoleDebug() +{ +#ifdef _MSC_VER + /* + * Print debug to output window if using VS. + */ + QObject::connect(&LRCInstance::behaviorController(), + &lrc::api::BehaviorController::debugMessageReceived, + [](const QString &message) { + OutputDebugStringA((message + "\n").toStdString().c_str()); + }); +#endif +} + +void +MainApplication::fileDebug(QFile *debugFile) +{ + QObject::connect(&LRCInstance::behaviorController(), + &lrc::api::BehaviorController::debugMessageReceived, + [debugFile](const QString &message) { + if (debugFile->open(QIODevice::WriteOnly | QIODevice::Append)) { + auto msg = (message + "\n").toStdString().c_str(); + debugFile->write(msg, qstrlen(msg)); + debugFile->close(); + } + }); +} + +void +MainApplication::exitApp() +{ + GlobalSystemTray::instance().hide(); +#ifdef Q_OS_WIN + FreeConsole(); +#endif +} + +char ** +MainApplication::parseInputArgument(int &argc, char *argv[], char *argToParse) +{ + /* + * Forcefully append argToParse. + */ + int oldArgc = argc; + argc = argc + 1 + 1; + char **newArgv = new char *[argc]; + for (int i = 0; i < oldArgc; i++) { + newArgv[i] = argv[i]; + } + newArgv[oldArgc] = argToParse; + newArgv[oldArgc + 1] = nullptr; + return newArgv; +} + +QString +MainApplication::getDebugFilePath() +{ + QDir logPath(QStandardPaths::writableLocation(QStandardPaths::AppLocalDataLocation)); + /* + * Since logPath will be .../Ring, we use cdUp to remove it. + */ + logPath.cdUp(); + return QString(logPath.absolutePath() + "/jami/jami.log"); +} + +void +MainApplication::loadTranslations() +{ + auto appDir = qApp->applicationDirPath() + "/"; + const auto locale_name = QLocale::system().name(); + const auto locale_lang = locale_name.split('_')[0]; + + QTranslator *qtTranslator_lang = new QTranslator(this); + QTranslator *qtTranslator_name = new QTranslator(this); + if (locale_name != locale_lang) { + if (qtTranslator_lang->load("qt_" + locale_lang, + QLibraryInfo::location(QLibraryInfo::TranslationsPath))) + installTranslator(qtTranslator_lang); + } + qtTranslator_name->load("qt_" + locale_name, + QLibraryInfo::location(QLibraryInfo::TranslationsPath)); + installTranslator(qtTranslator_name); + + QTranslator *lrcTranslator_lang = new QTranslator(this); + QTranslator *lrcTranslator_name = new QTranslator(this); + if (locale_name != locale_lang) { + if (lrcTranslator_lang->load(appDir + "share/libringclient/translations/lrc_" + locale_lang)) + installTranslator(lrcTranslator_lang); + } + if (lrcTranslator_name->load(appDir + "share/libringclient/translations/lrc_" + locale_name)) + installTranslator(lrcTranslator_name); + + QTranslator *mainTranslator_lang = new QTranslator(this); + QTranslator *mainTranslator_name = new QTranslator(this); + if (locale_name != locale_lang) { + if (mainTranslator_lang->load(appDir + "share/ring/translations/ring_client_windows_" + + locale_lang)) + installTranslator(mainTranslator_lang); + } + if (mainTranslator_name->load(appDir + "share/ring/translations/ring_client_windows_" + + locale_name)) + installTranslator(mainTranslator_name); +} + +void +MainApplication::initLrc() +{ + /* + * Init mainwindow and finish splash when mainwindow shows up. + */ + std::atomic_bool isMigrating(false); + LRCInstance::init( + [this, &isMigrating] { + /* + * TODO: splash screen for account migration. + */ + isMigrating = true; + while (isMigrating) { + this->processEvents(); + } + }, + [this, &isMigrating] { + while (!isMigrating) { + std::this_thread::sleep_for(std::chrono::milliseconds(10)); + } + isMigrating = false; + }); + LRCInstance::subscribeToDebugReceived(); + LRCInstance::getAPI().holdConferences = false; +} + +void +MainApplication::processInputArgument(bool &startMinimized) +{ + debugFile_ = std::make_unique(getDebugFilePath()); + QString uri = ""; + + for (auto string : QCoreApplication::arguments()) { + if (string.startsWith("jami:")) { + uri = string; + } else { + if (string == "-m" || string == "--minimized") { + startMinimized = true; + } + auto dbgFile = string == "-f" || string == "--file"; + auto dbgConsole = string == "-c" || string == "--vsconsole"; + if (dbgFile || dbgConsole) { + if (dbgFile) { + debugFile_->open(QIODevice::WriteOnly | QIODevice::Truncate); + debugFile_->close(); + fileDebug(debugFile_.get()); + } +#ifdef _MSC_VER + if (dbgConsole) { + vsConsoleDebug(); + } +#endif + } + } + } +} + +void +MainApplication::setApplicationFont() +{ + QFont font; + font.setFamily("Segoe UI"); + setFont(font); + QFontDatabase::addApplicationFont(":/images/FontAwesome.otf"); +} + +void +MainApplication::qmlInitialization() +{ + /* + * Register accountListModel type. + */ + QML_REGISTERTYPE(AccountListModel, 1, 0); + QML_REGISTERTYPE(DeviceItemListModel, 1, 0); + QML_REGISTERTYPE(PluginItemListModel, 1, 0); + QML_REGISTERTYPE(PreferenceItemListModel, 1, 0); + QML_REGISTERTYPE(BannedListModel, 1, 0); + QML_REGISTERTYPE(VideoCodecListModel, 1, 0); + QML_REGISTERTYPE(AudioCodecListModel, 1, 0); + QML_REGISTERTYPE(AccountsToMigrateListModel, 1, 0); + QML_REGISTERTYPE(AudioInputDeviceModel, 1, 0); + QML_REGISTERTYPE(AudioOutputDeviceModel, 1, 0); + QML_REGISTERTYPE(AudioManagerListModel, 1, 0); + QML_REGISTERTYPE(VideoInputDeviceModel, 1, 0); + QML_REGISTERTYPE(VideoFormatResolutionModel, 1, 0); + QML_REGISTERTYPE(VideoFormatFpsModel, 1, 0); + /* + * Register QQuickItem type. + */ + QML_REGISTERTYPE(PreviewRenderer, 1, 0); + QML_REGISTERTYPE(VideoCallPreviewRenderer, 1, 0); + QML_REGISTERTYPE(DistantRenderer, 1, 0); + QML_REGISTERTYPE(PhotoboothPreviewRender, 1, 0) + + /* + * Adapter - qmlRegisterSingletonType. + * Note: in future, if lrc is fully compatible with qml (C++ struct + * is readable in qml), the adapters can be optimized away. + */ + QML_REGISTERSINGLETONTYPE_URL(QStringLiteral("qrc:/src/constant/JamiTheme.qml"), + JamiTheme, + 1, + 0); + QML_REGISTERSINGLETONTYPE(CallAdapter, 1, 0); + + QML_REGISTERSINGLETONTYPE(MessagesAdapter, 1, 0); + QML_REGISTERSINGLETONTYPE(ConversationsAdapter, 1, 0); + QML_REGISTERSINGLETONTYPE(AvAdapter, 1, 0); + QML_REGISTERSINGLETONTYPE(ContactAdapter, 1, 0); + QML_REGISTERSINGLETONTYPE(ClientWrapper, 1, 0); + + //QML_REGISTERSINGLETONTYPE_WITH_INSTANCE(AccountAdapter, 1, 0); + //QML_REGISTERSINGLETONTYPE_WITH_INSTANCE(UtilsAdapter, 1, 0); + QML_REGISTERUNCREATABLE(AccountAdapter, 1, 0); + QML_REGISTERUNCREATABLE(UtilsAdapter, 1, 0); + QML_REGISTERUNCREATABLE(SettingsAdaptor, 1, 0); + QML_REGISTERUNCREATABLE(NameDirectory, 1, 0); + QML_REGISTERUNCREATABLE(LRCInstance, 1, 0); + + /* + * Lrc models - qmlRegisterUncreatableType & Q_DECLARE_METATYPE. + * This to make lrc models recognizable in qml. + */ + QML_REGISTERUNCREATABLE_IN_NAMESPACE(NewAccountModel, lrc::api, 1, 0); + QML_REGISTERUNCREATABLE_IN_NAMESPACE(BehaviorController, lrc::api, 1, 0); + QML_REGISTERUNCREATABLE_IN_NAMESPACE(DataTransferModel, lrc::api, 1, 0); + QML_REGISTERUNCREATABLE_IN_NAMESPACE(AVModel, lrc::api, 1, 0); + QML_REGISTERUNCREATABLE_IN_NAMESPACE(ContactModel, lrc::api, 1, 0); + QML_REGISTERUNCREATABLE_IN_NAMESPACE(ConversationModel, lrc::api, 1, 0); + QML_REGISTERUNCREATABLE_IN_NAMESPACE(NewCallModel, lrc::api, 1, 0); + QML_REGISTERUNCREATABLE_IN_NAMESPACE(PluginModel, lrc::api, 1, 0); + QML_REGISTERUNCREATABLE_IN_NAMESPACE(NewDeviceModel, lrc::api, 1, 0); + QML_REGISTERUNCREATABLE_IN_NAMESPACE(NewCodecModel, lrc::api, 1, 0); + QML_REGISTERUNCREATABLE_IN_NAMESPACE(PeerDiscoveryModel, lrc::api, 1, 0); + + /* + * Client models - qmlRegisterUncreatableType & Q_DECLARE_METATYPE. + * This to make client models recognizable in qml. + */ + QML_REGISTERUNCREATABLE(RenderManager, 1, 0); + + /* + * Namespaces - qmlRegisterUncreatableMetaObject. + */ + QML_REGISTERNAMESPACE(lrc::api::staticMetaObject, "Lrc", 1, 0); + QML_REGISTERNAMESPACE(lrc::api::account::staticMetaObject, "Account", 1, 0); + QML_REGISTERNAMESPACE(lrc::api::call::staticMetaObject, "Call", 1, 0); + QML_REGISTERNAMESPACE(lrc::api::datatransfer::staticMetaObject, "Datatransfer", 1, 0); + QML_REGISTERNAMESPACE(lrc::api::interaction::staticMetaObject, "Interaction", 1, 0); + QML_REGISTERNAMESPACE(lrc::api::video::staticMetaObject, "Video", 1, 0); + QML_REGISTERNAMESPACE(lrc::api::profile::staticMetaObject, "Profile", 1, 0); + + /* + * Add image provider. + */ + engine_->addImageProvider(QLatin1String("qrImage"), new QrImageProvider()); + engine_->addImageProvider(QLatin1String("tintedPixmap"), new TintedButtonImageProvider()); + + engine_->load(QUrl(QStringLiteral("qrc:/src/MainApplicationWindow.qml"))); +} + +MainApplication::~MainApplication() {} + +bool +MainApplication::applicationSetup() +{ +#ifdef Q_OS_LINUX + if (!getenv("QT_QPA_PLATFORMTHEME")) + setenv("QT_QPA_PLATFORMTHEME", "gtk3", true); +#endif + + /* + * Start debug console. + */ + for (auto string : QCoreApplication::arguments()) { + if (string == "-d" || string == "--debug") { + consoleDebug(); + } + } + + /* + * Remove old version files. + */ + Utils::removeOldVersions(); + + /* + * Load translations. + */ + loadTranslations(); + + /* + * Set font. + */ + setApplicationFont(); + +#if defined _MSC_VER && !COMPILE_ONLY + gnutls_global_init(); +#endif + + /* + * Init pixmap manipulator. + */ + GlobalInstances::setPixmapManipulator(std::make_unique()); + + /* + * Init lrc and its possible migration ui. + */ + initLrc(); + + /* + * Process input argument. + */ + bool startMinimized{false}; + processInputArgument(startMinimized); + + /* + * Create jami.net settings in Registry if it is not presented. + */ + QSettings settings("jami.net", "Jami"); + + /* + * Initialize qml components. + */ + qmlInitialization(); + + return true; +} diff --git a/src/mainapplication.h b/src/mainapplication.h new file mode 100644 index 00000000..ae51ac6a --- /dev/null +++ b/src/mainapplication.h @@ -0,0 +1,59 @@ +/* + * Copyright (C) 2020 by Savoir-faire Linux + * Author: Edric Ladent Milaret + * Author: Andreas Traczyk + * Author: Mingrui Zhang + * + * 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 . + */ + +#pragma once + +#include +#include +#include +#include + +#include + +class MainApplication : public QApplication +{ + Q_OBJECT + +public: + explicit MainApplication(int &argc, char **argv); + ~MainApplication(); + + bool applicationSetup(); + void exitApp(); + + static void applicationInitialization(); + static QString getDebugFilePath(); + static char **parseInputArgument(int &argc, char *argv[], char *argToParse); + +protected: + void consoleDebug(); + void vsConsoleDebug(); + void fileDebug(QFile *debugFile); + +private: + void loadTranslations(); + void initLrc(); + void processInputArgument(bool &startMinimized); + void setApplicationFont(); + void qmlInitialization(); + + std::unique_ptr debugFile_; + QQmlApplicationEngine *engine_; +}; diff --git a/src/mainview/MainView.qml b/src/mainview/MainView.qml new file mode 100644 index 00000000..6bf2ff5d --- /dev/null +++ b/src/mainview/MainView.qml @@ -0,0 +1,506 @@ + +/* + * Copyright (C) 2020 by Savoir-faire Linux + * Author: Mingrui Zhang + * + * 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 . + */ +import QtQuick 2.14 +import QtQuick.Window 2.14 +import QtQuick.Controls 2.14 +import QtQuick.Layouts 1.14 +import QtQuick.Controls.Universal 2.12 +import QtGraphicalEffects 1.14 +import net.jami.Models 1.0 + + +/* + * Import qml component files. + */ +import "components" +import "../settingsview" + +Window { + id: mainViewWindow + + property int minWidth: sidePanelViewStackPreferedWidth + property int minHeight: aboutPopUpDialog.contentHeight + + property int mainViewWindowPreferedWidth: 650 + property int mainViewWindowPreferedHeight: 600 + property int sidePanelViewStackPreferedWidth: 250 + property int welcomePageGroupPreferedWidth: 250 + property int aboutPopUpPreferedWidth: 250 + + + /* + * To calculate tab bar bottom border hidden rect left margin. + */ + property int tabBarLeftMargin: 8 + property int tabButtonShrinkSize: 8 + + signal noAccountIsAvailable + signal needToAddNewAccount + signal closeApp + + function newAccountAdded(index) { + mainViewWindowSidePanel.refreshAccountComboBox(index) + } + + function recursionStackViewItemMove(stackOne, stackTwo) { + + + /* + * Move all items (expect the bottom item) to stacktwo by the same order in stackone. + */ + if (stackOne.depth === 1) { + return + } + + var tempItem = stackOne.pop(StackView.Immediate) + recursionStackViewItemMove(stackOne, stackTwo) + stackTwo.push(tempItem, StackView.Immediate) + } + + title: "Jami" + visible: true + width: mainViewWindowPreferedWidth + height: mainViewWindowPreferedHeight + minimumWidth: minWidth + minimumHeight: minHeight + + Connections { + target: CallAdapter + + function onShowCallStack(accountId, convUid, forceReset) { + if (forceReset) { + callStackView.responsibleAccountId = accountId + callStackView.responsibleConvUid = convUid + } + + + /* + * Check if it is coming from the current responsible call, + * and push views onto the correct stackview + */ + if (callStackView.responsibleAccountId === accountId + && callStackView.responsibleConvUid === convUid) { + if (welcomeViewStack.visible) { + welcomeViewStack.pop(null, StackView.Immediate) + welcomeViewStack.push(callStackView, StackView.Immediate) + } else { + sidePanelViewStack.pop(null, StackView.Immediate) + sidePanelViewStack.push(callStackView, StackView.Immediate) + } + } + } + + function onCloseCallStack(accountId, convUid) { + + + /* + * Check if call stack view is on any of the stackview. + */ + if (callStackView.responsibleAccountId === accountId + && callStackView.responsibleConvUid === convUid) { + if (welcomeViewStack.find(function (item, index) { + return item.objectName === "callStackViewObject" + }) || sidePanelViewStack.find(function (item, index) { + return item.objectName === "callStackViewObject" + })) { + callStackView.needToCloseInCallConversationAndPotentialWindow() + if (welcomeViewStack.visible) { + welcomeViewStack.pop(null, StackView.Immediate) + welcomeViewStack.push(communicationPageMessageWebView, + StackView.Immediate) + } else { + sidePanelViewStack.pop(null, StackView.Immediate) + sidePanelViewStack.push( + communicationPageMessageWebView, + StackView.Immediate) + } + } + } + } + + function onIncomingCallNeedToSetupMainView(accountId, convUid) { + + + /* + * Set up the call stack view that is needed by call overlay. + */ + welcomeViewStack.pop(null, StackView.Immediate) + sidePanelViewStack.pop(null, StackView.Immediate) + + var index = ClientWrapper.utilsAdaptor.getCurrAccList().indexOf(accountId) + var name = ClientWrapper.utilsAdaptor.getBestName(accountId, convUid) + var id = ClientWrapper.utilsAdaptor.getBestId(accountId, convUid) + + communicationPageMessageWebView.headerUserAliasLabelText = name + communicationPageMessageWebView.headerUserUserNameLabelText = (name !== id) ? id : "" + + callStackView.needToCloseInCallConversationAndPotentialWindow() + callStackView.setCorrspondingMessageWebView( + communicationPageMessageWebView) + + callStackView.responsibleAccountId = accountId + callStackView.responsibleConvUid = convUid + callStackView.updateCorrspondingUI() + + mainViewWindowSidePanel.needToChangeToAccount(accountId, index) + ConversationsAdapter.selectConversation(accountId, convUid) + + MessagesAdapter.setupChatView(convUid) + } + } + + StackLayout { + id: mainViewStackLayout + + anchors.fill: parent + + currentIndex: 0 + + SplitView { + id: splitView + + Layout.fillWidth: true + Layout.fillHeight: true + + width: mainViewWindow.width + height: mainViewWindow.height + + handle: Rectangle { + implicitWidth: JamiTheme.splitViewHandlePreferedWidth + implicitHeight: splitView.height + color: SplitHandle.pressed ? JamiTheme.pressColor : (SplitHandle.hovered ? JamiTheme.hoverColor : JamiTheme.tabbarBorderColor) + } + + StackView { + id: sidePanelViewStack + + property int maximumWidth: sidePanelViewStackPreferedWidth + 100 + + initialItem: mainViewWindowSidePanel + + SplitView.minimumWidth: sidePanelViewStackPreferedWidth + SplitView.maximumWidth: maximumWidth + SplitView.fillHeight: true + + clip: true + } + + StackView { + id: welcomeViewStack + + initialItem: welcomePage + + SplitView.maximumWidth: splitView.width - sidePanelViewStack.width + SplitView.fillHeight: true + + clip: true + } + } + + SettingsView { + id: settingsView + + Layout.fillWidth: true + Layout.fillHeight: true + + onSettingsViewWindowNeedToShowMainViewWindow: { + mainViewWindowSidePanel.refreshAccountComboBox( + accountDeleted ? 0 : -1) + mainViewStackLayout.currentIndex = 0 + } + + onSettingsViewWindowNeedToShowNewWizardWindow: { + mainViewWindow.noAccountIsAvailable() + } + } + } + + AccountListModel { + id: accountListModel + } + + SidePanel { + id: mainViewWindowSidePanel + + onSettingBtnClicked_AccountComboBox: { + mainViewStackLayout.currentIndex = 1 + } + + onConversationSmartListNeedToAccessMessageWebView: { + + communicationPageMessageWebView.headerUserAliasLabelText = currentUserAlias + communicationPageMessageWebView.headerUserUserNameLabelText = currentUserDisplayName + + callStackView.needToCloseInCallConversationAndPotentialWindow() + callStackView.responsibleAccountId = ClientWrapper.utilsAdaptor.getCurrAccId() + callStackView.responsibleConvUid = currentUID + callStackView.updateCorrspondingUI() + + if (callStackViewShouldShow) { + if (callStateStr == "Talking" || callStateStr == "Hold") { + ClientWrapper.utilsAdaptor.setCurrentCall( + ClientWrapper.utilsAdaptor.getCurrAccId(), + currentUID) + if (isAudioOnly) + callStackView.showAudioCallPage() + else + callStackView.showVideoCallPage( + ClientWrapper.utilsAdaptor.getCallId( + callStackView.responsibleAccountId, + callStackView.responsibleConvUid)) + } else { + callStackView.showOutgoingCallPage(callStateStr) + } + } + + + /* + * Set up chatview. + */ + MessagesAdapter.setupChatView(currentUID) + callStackView.setCorrspondingMessageWebView( + communicationPageMessageWebView) + + if (welcomeViewStack.find(function (item, index) { + return item.objectName === "communicationPageMessageWebView" + }) || sidePanelViewStack.find(function (item, index) { + return item.objectName === "communicationPageMessageWebView" + })) { + if (!callStackViewShouldShow) + return + } + + + /* + * Push messageWebView or callStackView onto the correct stackview + */ + welcomeViewStack.pop(null, StackView.Immediate) + sidePanelViewStack.pop(null, StackView.Immediate) + + if (sidePanelViewStack.visible && welcomeViewStack.visible) { + if (callStackViewShouldShow) { + welcomeViewStack.push(callStackView) + } else { + welcomeViewStack.push(communicationPageMessageWebView) + } + } else if (sidePanelViewStack.visible + && !welcomeViewStack.visible) { + if (callStackViewShouldShow) { + sidePanelViewStack.push(callStackView) + } else { + sidePanelViewStack.push(communicationPageMessageWebView) + } + } else if (!sidePanelViewStack.visible + && !welcomeViewStack.visible) { + if (callStackViewShouldShow) { + sidePanelViewStack.push(callStackView) + } else { + sidePanelViewStack.push(communicationPageMessageWebView) + } + } + } + + onAccountComboBoxNeedToShowWelcomePage: { + + + /* + * If the item argument is specified, all items down to (but not including) item will be popped. + */ + welcomeViewStack.pop(welcomePage) + welcomePage.currentAccountIndex = index + qrDialog.currentAccountIndex = index + } + + onConversationSmartListViewNeedToShowWelcomePage: { + welcomeViewStack.pop(welcomePage) + welcomePage.currentAccountIndex = 0 + qrDialog.currentAccountIndex = 0 + } + + onAccountSignalsReconnect: { + MessagesAdapter.accountChangedSetUp(accountId) + } + + onNeedToUpdateConversationForAddedContact: { + MessagesAdapter.updateConversationForAddedContact() + mainViewWindowSidePanel.clearContactSearchBar() + mainViewWindowSidePanel.forceReselectConversationSmartListCurrentIndex() + } + + onNeedToAddNewAccount: { + mainViewWindow.needToAddNewAccount() + } + } + + CallStackView { + id: callStackView + + visible: false + + objectName: "callStackViewObject" + + onCallPageBackButtonIsClicked: { + mainViewWindowSidePanel.deselectConversationSmartList() + if (welcomeViewStack.visible) + welcomeViewStack.pop(welcomePage) + else if (sidePanelViewStack.visible) + sidePanelViewStack.pop(mainViewWindowSidePanel) + } + + onOutgoingCallPageBackButtonIsClicked: { + mainViewWindowSidePanel.deselectConversationSmartList() + if (welcomeViewStack.visible) + welcomeViewStack.pop(welcomePage) + else if (sidePanelViewStack.visible) + sidePanelViewStack.pop(mainViewWindowSidePanel) + } + } + + WelcomePage { + id: welcomePage + visible: false + } + + MessageWebView { + id: communicationPageMessageWebView + + objectName: "communicationPageMessageWebView" + + signal toSendMessageContentSaved(string arg) + signal toMessagesCleared + signal toMessagesLoaded + + visible: false + + Connections { + target: MessagesAdapter + + function onNeedToUpdateSmartList() { + mainViewWindowSidePanel.forceUpdateConversationSmartListView() + } + } + + onNeedToGoBackToWelcomeView: { + mainViewWindowSidePanel.deselectConversationSmartList() + if (communicationPageMessageWebView.visible + && !welcomeViewStack.visible) { + sidePanelViewStack.pop() + } else if (communicationPageMessageWebView.visible + && welcomeViewStack.visible) { + welcomeViewStack.pop() + } + } + + Component.onCompleted: { + + + /* + * Set qml MessageWebView object pointer to c++. + */ + MessagesAdapter.setQmlObject(this) + } + } + + onWidthChanged: { + + + /* + * Hide unnecessary stackview when width is changed. + */ + if (mainViewWindow.width < sidePanelViewStackPreferedWidth + + welcomePageGroupPreferedWidth - 5 + && welcomeViewStack.visible) { + welcomeViewStack.visible = false + + + /* + * The find callback function is called for each item in the stack. + */ + var inWelcomeViewStack = welcomeViewStack.find( + function (item, index) { + return index > 0 + }) + if (inWelcomeViewStack) { + recursionStackViewItemMove(welcomeViewStack, sidePanelViewStack) + } + + sidePanelViewStack.maximumWidth = splitView.width + + mainViewWindow.update() + } else if (mainViewWindow.width >= sidePanelViewStackPreferedWidth + + welcomePageGroupPreferedWidth + 5 + && !welcomeViewStack.visible) { + welcomeViewStack.visible = true + + var inSidePanelViewStack = sidePanelViewStack.find( + function (item, index) { + return index > 0 + }) + if (inSidePanelViewStack) { + recursionStackViewItemMove(sidePanelViewStack, welcomeViewStack) + } + + sidePanelViewStack.maximumWidth = sidePanelViewStackPreferedWidth + 100 + + mainViewWindow.update() + } + } + + AboutPopUp { + id: aboutPopUpDialog + + x: Math.round((mainViewWindow.width - width) / 2) + y: Math.round((mainViewWindow.height - height) / 2) + width: Math.max(mainViewWindow.width / 2, aboutPopUpPreferedWidth) + height: aboutPopUpDialog.contentHeight + } + + WelcomePageQrDialog { + id: qrDialog + + x: Math.round((mainViewWindow.width - width) / 2) + y: Math.round((mainViewWindow.height - height) / 2) + width: qrDialog.contentHeight + height: qrDialog.contentHeight + } + + RecordBox{ + id: recordBox + visible: false + } + + UserProfile { + id: userProfile + + x: Math.round((mainViewWindow.width - width) / 2) + y: Math.round((mainViewWindow.height - height) / 2) + width: Math.max(mainViewWindow.width / 2, aboutPopUpPreferedWidth) + height: userProfile.contentHeight + } + + Component.onCompleted: { + CallAdapter.initQmlObject() + } + + onClosing: { + close.accepted = false + mainViewWindow.hide() + mainViewWindow.closeApp() + } +} diff --git a/src/mainview/components/AboutPopUp.qml b/src/mainview/components/AboutPopUp.qml new file mode 100644 index 00000000..f13c46a0 --- /dev/null +++ b/src/mainview/components/AboutPopUp.qml @@ -0,0 +1,308 @@ + +/* + * Copyright (C) 2020 by Savoir-faire Linux + * Author: Mingrui Zhang + * + * 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 . + */ +import QtQuick 2.14 +import QtQuick.Controls 2.14 +import QtQuick.Layouts 1.14 +import net.jami.Models 1.0 + +import "../../commoncomponents" + +Dialog { + id: aboutPopUp + + + /* + * When dialog is opened, trigger mainViewWindow overlay which is defined in overlay.model (model : true is necessary). + */ + modal: true + + + /* + * Content height + margin. + */ + contentHeight: aboutPopUpContentRectColumnLayout.height + 5 * 7 + + ProjectCreditsScrollView { + id: projectCreditsScrollView + + visible: false + } + + ChangeLogScrollView { + id: changeLogScrollView + + visible: false + } + + Rectangle { + id: aboutPopUpContentRect + + anchors.fill: parent + + ColumnLayout { + id: aboutPopUpContentRectColumnLayout + + Image { + id: aboutPopUPJamiLogoImage + + Layout.alignment: Qt.AlignCenter + Layout.preferredWidth: aboutPopUpContentRect.width + Layout.preferredHeight: 100 + + fillMode: Image.PreserveAspectFit + source: "qrc:/images/logo-jami-standard-coul.png" + mipmap: true + } + + Label { + id: jamiVersionText + + Layout.alignment: Qt.AlignCenter + Layout.preferredWidth: aboutPopUpContentRect.width + Layout.preferredHeight: textMetricsjamiVersionText.boundingRect.height + + font.pointSize: JamiTheme.textFontSize - 2 + + horizontalAlignment: Text.AlignHCenter + verticalAlignment: Text.AlignVCenter + + text: textMetricsjamiVersionText.text + + TextMetrics { + id: textMetricsjamiVersionText + font: jamiVersionText.font + text: qsTr("version") + ": " + ClientWrapper.utilsAdaptor.getVersionStr() + } + } + + Label { + id: jamiSlogansText + + Layout.alignment: Qt.AlignCenter + Layout.preferredWidth: aboutPopUpContentRect.width + Layout.preferredHeight: textMetricsjamiSlogansText.boundingRect.height + Layout.topMargin: 5 + + wrapMode: Text.WordWrap + font.pointSize: JamiTheme.textFontSize - 2 + + horizontalAlignment: Text.AlignHCenter + verticalAlignment: Text.AlignVCenter + + text: textMetricsjamiSlogansText.text + + TextMetrics { + id: textMetricsjamiSlogansText + font: jamiSlogansText.font + text: qsTr("Free as in Freedom") + } + } + + Label { + id: jamiDeclarationText + + Layout.alignment: Qt.AlignCenter + Layout.preferredWidth: aboutPopUpContentRect.width + Layout.preferredHeight: 40 + Layout.topMargin: 5 + + wrapMode: Text.WordWrap + font.pointSize: JamiTheme.textFontSize - 2 + + horizontalAlignment: Text.AlignHCenter + verticalAlignment: Text.AlignVCenter + + + /* + * TextMetrics does not work for multi-line. + */ + text: qsTr("The Microsoft Windows client for Jami.\nJami is a secured and distributed communciation software.") + } + + Label { + id: jamiDeclarationHyperText + + Layout.alignment: Qt.AlignCenter + + + /* + * Strangely, hoveredLink works badly when width grows too large + */ + Layout.preferredWidth: 50 + Layout.preferredHeight: textMetricsjamiDeclarationHyperText.boundingRect.height + Layout.topMargin: 5 + Layout.bottomMargin: 5 + + font.pointSize: JamiTheme.textFontSize - 2 + + horizontalAlignment: Text.AlignHCenter + verticalAlignment: Text.AlignVCenter + + text: textMetricsjamiDeclarationHyperText.text + onLinkActivated: Qt.openUrlExternally(link) + + TextMetrics { + id: textMetricsjamiDeclarationHyperText + font: jamiDeclarationHyperText.font + text: 'jami.net' + } + + MouseArea { + anchors.fill: parent + + + /* + * We don't want to eat clicks on the Text. + */ + acceptedButtons: Qt.NoButton + cursorShape: parent.hoveredLink ? Qt.PointingHandCursor : Qt.ArrowCursor + } + } + + Label { + id: jamiDeclarationYearText + + Layout.alignment: Qt.AlignCenter + Layout.preferredWidth: aboutPopUpContentRect.width + Layout.preferredHeight: textMetricsjamiDeclarationYearText.boundingRect.height + Layout.bottomMargin: 5 + + font.pointSize: JamiTheme.textFontSize - 2 + + horizontalAlignment: Text.AlignHCenter + verticalAlignment: Text.AlignVCenter + + text: textMetricsjamiDeclarationYearText.text + + TextMetrics { + id: textMetricsjamiDeclarationYearText + font: jamiDeclarationYearText.font + text: "© 2015-2020 Savoir-faire Linux" + } + } + + Label { + id: jamiNoneWarrantyHyperText + + Layout.alignment: Qt.AlignCenter + Layout.preferredWidth: Math.min(300, + aboutPopUpContentRect.width) + Layout.preferredHeight: textMetricsjamiNoneWarrantyHyperText.boundingRect.height * 2 + Layout.bottomMargin: 10 + + wrapMode: Text.WordWrap + font.pointSize: JamiTheme.textFontSize - 3 + + horizontalAlignment: Text.AlignHCenter + verticalAlignment: Text.AlignVCenter + + text: textMetricsjamiNoneWarrantyHyperText.text + onLinkActivated: Qt.openUrlExternally(link) + + TextMetrics { + id: textMetricsjamiNoneWarrantyHyperText + font: jamiDeclarationHyperText.font + text: 'This program comes with absolutely no warranty.See the GNU General Public License, version 3 or later for details.' + } + + MouseArea { + anchors.fill: parent + acceptedButtons: Qt.NoButton + cursorShape: parent.hoveredLink ? Qt.PointingHandCursor : Qt.ArrowCursor + } + } + + Rectangle { + id: buttonGroupChangeLogAndCredits + + Layout.alignment: Qt.AlignCenter + Layout.preferredWidth: aboutPopUpContentRect.width + Layout.preferredHeight: 30 + Layout.bottomMargin: 10 + + RowLayout { + id: buttonGroupChangeLogAndCreditsRowLayout + + anchors.fill: parent + + HoverableButton { + id: changeLogButton + + Layout.alignment: Qt.AlignCenter + Layout.preferredWidth: textMetricschangeLogButton.boundingRect.width + 20 + Layout.preferredHeight: 30 + + radius: 10 + fontPointSize: JamiTheme.textFontSize - 2 + text: textMetricschangeLogButton.text + + TextMetrics { + id: textMetricschangeLogButton + font: changeLogButton.font + text: qsTr("Change Log") + } + + onClicked: { + if (changeLogOrCreditsStack.depth > 1) { + changeLogOrCreditsStack.pop() + } + } + } + + HoverableButton { + id: creditsButton + + Layout.alignment: Qt.AlignCenter + Layout.preferredWidth: changeLogButton.width + Layout.preferredHeight: 30 + + radius: 10 + fontPointSize: JamiTheme.textFontSize - 2 + text: qsTr("Credits") + + onClicked: { + if (changeLogOrCreditsStack.depth == 1) { + changeLogOrCreditsStack.push( + projectCreditsScrollView) + } + } + } + } + } + + StackView { + id: changeLogOrCreditsStack + + Layout.alignment: Qt.AlignCenter + Layout.preferredWidth: aboutPopUpContentRect.width + Layout.preferredHeight: 150 + Layout.bottomMargin: 5 + + initialItem: changeLogScrollView + + clip: true + } + } + } + + background: Rectangle { + border.width: 0 + radius: 10 + } +} diff --git a/src/mainview/components/AccountComboBox.qml b/src/mainview/components/AccountComboBox.qml new file mode 100644 index 00000000..23225f78 --- /dev/null +++ b/src/mainview/components/AccountComboBox.qml @@ -0,0 +1,303 @@ + +/* + * Copyright (C) 2020 by Savoir-faire Linux + * Author: Mingrui Zhang + * + * 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 . + */ +import QtQuick 2.14 +import QtQuick.Controls 2.14 +import QtQuick.Layouts 1.14 +import net.jami.Models 1.0 + +import "../../commoncomponents" + +ComboBox { + id: accountComboBox + + signal accountChanged(int index) + signal needToBackToWelcomePage(int index) + signal needToUpdateSmartList(string accountId) + signal newAccountButtonClicked + signal settingBtnClicked + + currentIndex: 0 + + function backToWelcomePage(index) { + accountComboBox.needToBackToWelcomePage(index) + } + + function updateSmartList(accountId) { + accountComboBox.needToUpdateSmartList(accountId) + } + + + /* + * Refresh every item in accountListModel. + */ + function updateAccountListModel() { + accountListModel.dataChanged(accountListModel.index(0, 0), + accountListModel.index( + accountListModel.rowCount() - 1, 0)) + } + + + /* + * Reset accountListModel. + */ + function resetAccountListModel() { + accountListModel.reset() + } + + Image { + id: userImageRoot + + anchors.left: accountComboBox.left + anchors.leftMargin: 5 + anchors.verticalCenter: accountComboBox.verticalCenter + + width: accountComboBox.height - 10 + height: accountComboBox.height - 10 + + fillMode: Image.PreserveAspectFit + + + /* + * Base 64 format + */ + source: { + if (currentIndex !== -1) + return "data:image/png;base64," + accountListModel.data( + accountListModel.index( + accountComboBox.currentIndex, 0), 259) + else + return source + } + mipmap: true + + Rectangle { + id: presenseRect + + anchors.right: userImageRoot.right + anchors.rightMargin: 1 + anchors.bottom: userImageRoot.bottom + anchors.bottomMargin: 2 + + width: 14 + height: 14 + + + /* + * Visible when account is registered, enum REGISTERED == 5. + */ + visible: { + if (currentIndex !== -1) + return accountListModel.data( + accountListModel.index( + accountComboBox.currentIndex, 0), 261) === 5 + else + return visible + } + + Rectangle { + id: presenseCycle + + anchors.centerIn: presenseRect + + width: 10 + height: 10 + + radius: 30 + color: JamiTheme.presenceGreen + } + + radius: 30 + color: "white" + } + } + + Text { + id: textUserAliasRoot + + anchors.left: userImageRoot.right + anchors.leftMargin: 10 + anchors.top: rootItemBackground.top + anchors.topMargin: 5 + + text: textMetricsUserAliasRoot.elidedText + font.pointSize: JamiTheme.textFontSize + } + + Text { + id: textUsernameRoot + + anchors.left: userImageRoot.right + anchors.leftMargin: 10 + anchors.top: textUserAliasRoot.bottom + anchors.topMargin: 5 + + text: textMetricsUsernameRoot.elidedText + font.pointSize: JamiTheme.textFontSize + color: JamiTheme.faddedFontColor + } + + TextMetrics { + id: textMetricsUserAliasRoot + + font: textUserAliasRoot.font + elide: Text.ElideMiddle + elideWidth: accountComboBox.width - userImageRoot.width - settingsButton.width - 25 + + + /* + * Role::Alias + */ + text: { + if (currentIndex !== -1) + return accountListModel.data(accountListModel.index( + accountComboBox.currentIndex, + 0), 257) + else + return text + } + } + + TextMetrics { + id: textMetricsUsernameRoot + + font: textUsernameRoot.font + elide: Text.ElideMiddle + elideWidth: accountComboBox.width - userImageRoot.width - settingsButton.width - 25 + + + /* + * Role::Username + */ + text: { + if (currentIndex !== -1) + return accountListModel.data(accountListModel.index( + accountComboBox.currentIndex, + 0), 258) + else + return text + } + } + + HoverableButton { + id: settingsButton + + anchors.right: accountComboBox.right + anchors.rightMargin: 10 + anchors.verticalCenter: accountComboBox.verticalCenter + + buttonImageHeight: height - 8 + buttonImageWidth: width - 8 + source: "qrc:/images/icons/round-settings-24px.svg" + radius: height / 2 + width: 25 + height: 25 + + onClicked: { + settingBtnClicked() + } + } + + background: Rectangle { + id: rootItemBackground + + implicitWidth: accountComboBox.width + implicitHeight: accountComboBox.height + + border.width: 0 + } + + MouseArea { + id: comboBoxRootMouseArea + + anchors.fill: parent + + hoverEnabled: true + propagateComposedEvents: true + + onPressed: { + if (isMouseOnSettingsButton(mouse)) { + settingsButton.backgroundColor = JamiTheme.pressColor + settingsButton.clicked() + } else + rootItemBackground.color = JamiTheme.pressColor + } + onReleased: { + if (isMouseOnSettingsButton(mouse)) { + settingsButton.backgroundColor = JamiTheme.releaseColor + } else { + rootItemBackground.color = JamiTheme.releaseColor + if (comboBoxPopup.opened) { + accountComboBox.popup.close() + } else { + accountComboBox.popup.open() + } + } + } + onEntered: { + rootItemBackground.color = JamiTheme.hoverColor + } + onExited: { + rootItemBackground.color = "white" + } + onMouseXChanged: { + + + /* + * Manually making settings button hover. + */ + if (isMouseOnSettingsButton(mouse)) { + settingsButton.backgroundColor = JamiTheme.hoverColor + rootItemBackground.color = "white" + } else { + settingsButton.backgroundColor = "white" + rootItemBackground.color = JamiTheme.hoverColor + } + } + function isMouseOnSettingsButton(mouse) { + var mousePos = mapToItem(comboBoxRootMouseArea, mouse.x, mouse.y) + var settingsButtonPos = mapToItem(comboBoxRootMouseArea, + settingsButton.x, + settingsButton.y) + if ((mousePos.x >= settingsButtonPos.x + && mousePos.x <= settingsButtonPos.x + settingsButton.width) + && (mousePos.y >= settingsButtonPos.y + && mousePos.y <= settingsButtonPos.y + settingsButton.height)) + return true + return false + } + } + + indicator: null + + + /* + * Overwrite the combo box pop up to add footer (for add accounts). + */ + popup: AccountComboBoxPopup { + id: comboBoxPopup + + onAccountNeedToChange: { + accountComboBox.accountChanged(index) + } + + onNewAccountButtonClicked: { + accountComboBox.newAccountButtonClicked() + } + } +} diff --git a/src/mainview/components/AccountComboBoxPopup.qml b/src/mainview/components/AccountComboBoxPopup.qml new file mode 100644 index 00000000..42a17fbc --- /dev/null +++ b/src/mainview/components/AccountComboBoxPopup.qml @@ -0,0 +1,180 @@ + +/* + * Copyright (C) 2020 by Savoir-faire Linux + * Author: Mingrui Zhang + * + * 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 . + */ +import QtQuick 2.14 +import QtQuick.Controls 2.14 +import QtQuick.Layouts 1.14 +import net.jami.Models 1.0 + +import "../../commoncomponents" + +Popup { + id: comboBoxPopup + + property bool toogleUpdatePopupHeight: false + + signal accountNeedToChange(int index) + signal newAccountButtonClicked + + y: accountComboBox.height - 1 + implicitWidth: accountComboBox.width - 1 + + + /* + * Hack - limite the accounts that can be shown. + */ + implicitHeight: { + comboBoxPopup.visible + return Math.min(accountComboBox.height * Math.min( + 5, accountListModel.rowCount() + 1), + sidePanelRect.height) + } + padding: 0 + + contentItem: ListView { + id: comboBoxPopupListView + + + /* + * In list view, index is an interger. + */ + clip: true + model: accountListModel + implicitHeight: contentHeight + delegate: ItemDelegate { + + Image { + id: userImage + + anchors.left: parent.left + anchors.leftMargin: 5 + anchors.verticalCenter: parent.verticalCenter + + width: 30 + height: parent.height + + fillMode: Image.PreserveAspectFit + mipmap: true + + + /* + * Role::Picture + */ + source: "data:image/png;base64," + accountListModel.data( + accountListModel.index(index, 0), 259) + } + + Text { + id: textUserAliasPopup + + anchors.left: userImage.right + anchors.leftMargin: 10 + anchors.top: itemCoboBackground.top + anchors.topMargin: 5 + + text: textMetricsUserAliasPopup.elidedText + font.pointSize: JamiTheme.textFontSize + } + + Text { + id: textUsernamePopup + + anchors.left: userImage.right + anchors.leftMargin: 10 + anchors.top: textUserAliasPopup.bottom + anchors.topMargin: 5 + + text: textMetricsUsernamePopup.elidedText + font.pointSize: JamiTheme.textFontSize + color: JamiTheme.faddedFontColor + } + + TextMetrics { + id: textMetricsUserAliasPopup + elide: Text.ElideMiddle + elideWidth: accountComboBox.width - userImage.width - settingsButton.width - 30 + text: Alias + } + + TextMetrics { + id: textMetricsUsernamePopup + elide: Text.ElideMiddle + elideWidth: accountComboBox.width - userImage.width - settingsButton.width - 30 + text: Username + } + + background: Rectangle { + id: itemCoboBackground + + implicitWidth: accountComboBox.width + implicitHeight: accountComboBox.height + border.width: 0 + } + + MouseArea { + anchors.fill: parent + hoverEnabled: true + onPressed: { + itemCoboBackground.color = JamiTheme.pressColor + } + onReleased: { + itemCoboBackground.color = JamiTheme.releaseColor + currentIndex = index + comboBoxPopup.close() + comboBoxPopup.accountNeedToChange(index) + } + onEntered: { + itemCoboBackground.color = JamiTheme.hoverColor + } + onExited: { + itemCoboBackground.color = "white" + } + } + } + + footer: HoverableButton { + id: comboBoxFooterItem + + implicitWidth: accountComboBox.width + implicitHeight: accountComboBox.height + + text: qsTr("Add Account") + "+" + backgroundColor: "white" + onExitColor: "white" + + onClicked: { + comboBoxPopup.close() + comboBoxPopup.newAccountButtonClicked() + } + } + + ScrollIndicator.vertical: ScrollIndicator {} + } + background: Rectangle { + id: accountComboBoxPopup + + CustomBorder { + commonBorder: false + lBorderwidth: 0 + rBorderwidth: 1 + tBorderwidth: 0 + bBorderwidth: 1 + borderColor: JamiTheme.tabbarBorderColor + } + } +} diff --git a/src/mainview/components/AudioCallPage.qml b/src/mainview/components/AudioCallPage.qml new file mode 100644 index 00000000..1292f30a --- /dev/null +++ b/src/mainview/components/AudioCallPage.qml @@ -0,0 +1,248 @@ + +/* + * Copyright (C) 2020 by Savoir-faire Linux + * Author: Mingrui Zhang + * + * 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 . + */ +import QtQuick 2.14 +import QtQuick.Controls 2.14 +import QtQuick.Layouts 1.14 +import QtQuick.Controls.Universal 2.12 +import net.jami.Models 1.0 + +import "../../commoncomponents" + +Rectangle { + id: audioCallPageRect + + property string contactImgSource: "" + property string bestName: "Best Name" + property string bestId: "Best Id" + + property var corrspondingMessageWebView: null + + signal audioCallPageBackButtonIsClicked + + function updateUI(accountId, convUid) { + contactImgSource = "data:image/png;base64," + ClientWrapper.utilsAdaptor.getContactImageString( + accountId, convUid) + bestName = ClientWrapper.utilsAdaptor.getBestName(accountId, convUid) + + var id = ClientWrapper.utilsAdaptor.getBestId(accountId, convUid) + bestId = (bestName !== id) ? id : "" + } + + function setAudioCallPageCorrspondingMessageWebView(webViewId) { + corrspondingMessageWebView = webViewId + corrspondingMessageWebView.needToHideConversationInCall.disconnect( + closeInCallConversation) + corrspondingMessageWebView.needToHideConversationInCall.connect( + closeInCallConversation) + } + + function closeInCallConversation() { + if (inAudioCallMessageWebViewStack.visible) { + corrspondingMessageWebView.resetMessagingHeaderBackButtonSource( + true) + corrspondingMessageWebView.setMessagingHeaderButtonsVisible(true) + inAudioCallMessageWebViewStack.visible = false + inAudioCallMessageWebViewStack.clear() + } + } + + function closeContextMenuAndRelatedWindows() { + audioCallOverlay.closePotentialContactPicker() + } + + anchors.fill: parent + + SplitView { + id: mainColumnLayout + + anchors.fill: parent + + orientation: Qt.Vertical + + handle: Rectangle { + implicitWidth: audioCallPageRect.width + implicitHeight: JamiTheme.splitViewHandlePreferedWidth + color: SplitHandle.pressed ? JamiTheme.pressColor : (SplitHandle.hovered ? JamiTheme.hoverColor : JamiTheme.tabbarBorderColor) + } + + Rectangle { + id: audioCallPageMainRect + + SplitView.preferredHeight: (audioCallPageRect.height / 3) * 2 + SplitView.minimumHeight: audioCallPageRect.height / 2 + 20 + SplitView.fillWidth: true + + CallOverlay { + id: audioCallOverlay + + anchors.fill: parent + + Connections { + target: CallAdapter + + function onUpdateTimeText(time) { + audioCallOverlay.timeText = time + } + + function onUpdateOverlay(isPaused, isAudioOnly, isAudioMuted, isVideoMuted, isRecording, isSIP, isConferenceCall, bestName) { + audioCallOverlay.showOnHoldImage(isPaused) + audioCallPageRectCentralRect.visible = !isPaused + audioCallOverlay.updateButtonStatus(isPaused, + isAudioOnly, + isAudioMuted, + isVideoMuted, + isRecording, isSIP, + isConferenceCall) + audioCallOverlay.bestName = bestName + } + + function onShowOnHoldLabel(isPaused) { + audioCallOverlay.showOnHoldImage(isPaused) + audioCallPageRectCentralRect.visible = !isPaused + } + } + + onBackButtonIsClicked: { + if (inAudioCallMessageWebViewStack.visible) { + corrspondingMessageWebView.resetMessagingHeaderBackButtonSource( + true) + corrspondingMessageWebView.setMessagingHeaderButtonsVisible( + true) + inAudioCallMessageWebViewStack.visible = false + inAudioCallMessageWebViewStack.clear() + } + audioCallPageRect.audioCallPageBackButtonIsClicked() + } + + onOverlayChatButtonClicked: { + if (inAudioCallMessageWebViewStack.visible) { + corrspondingMessageWebView.resetMessagingHeaderBackButtonSource( + true) + corrspondingMessageWebView.setMessagingHeaderButtonsVisible( + true) + inAudioCallMessageWebViewStack.visible = false + inAudioCallMessageWebViewStack.clear() + } else { + corrspondingMessageWebView.resetMessagingHeaderBackButtonSource( + false) + corrspondingMessageWebView.setMessagingHeaderButtonsVisible( + false) + inAudioCallMessageWebViewStack.visible = true + inAudioCallMessageWebViewStack.push( + corrspondingMessageWebView) + } + } + } + + Rectangle { + id: audioCallPageRectCentralRect + + anchors.centerIn: parent + + width: audioCallPageRect.width + height: audioCallPageRegisteredNameText.height + + audioCallPageIdText.height + contactImage.height + 10 + + ColumnLayout { + id: audioCallPageRectColumnLayout + + Image { + id: contactImage + + Layout.alignment: Qt.AlignCenter + + Layout.preferredWidth: 100 + Layout.preferredHeight: 100 + + fillMode: Image.PreserveAspectFit + source: contactImgSource + asynchronous: true + } + + Text { + id: audioCallPageRegisteredNameText + + Layout.alignment: Qt.AlignCenter + + Layout.preferredWidth: audioCallPageRectCentralRect.width + Layout.preferredHeight: 50 + + font.pointSize: JamiTheme.textFontSize + 3 + + horizontalAlignment: Text.AlignHCenter + verticalAlignment: Text.AlignVCenter + + text: textMetricsAudioCallPageRegisteredNameText.elidedText + color: "white" + + TextMetrics { + id: textMetricsAudioCallPageRegisteredNameText + font: audioCallPageRegisteredNameText.font + text: bestName + elideWidth: audioCallPageRectCentralRect.width - 50 + elide: Qt.ElideMiddle + } + } + + Text { + id: audioCallPageIdText + + Layout.alignment: Qt.AlignCenter + + Layout.preferredWidth: audioCallPageRectCentralRect.width + Layout.preferredHeight: 30 + + font.pointSize: JamiTheme.textFontSize + + horizontalAlignment: Text.AlignHCenter + verticalAlignment: Text.AlignVCenter + + text: textMetricsAudioCallPageIdText.elidedText + color: "white" + + TextMetrics { + id: textMetricsAudioCallPageIdText + font: audioCallPageIdText.font + text: bestId + elideWidth: audioCallPageRectCentralRect.width - 50 + elide: Qt.ElideMiddle + } + } + } + + color: "transparent" + } + + color: "transparent" + } + + StackView { + id: inAudioCallMessageWebViewStack + + SplitView.preferredHeight: audioCallPageRect.height / 3 + SplitView.fillWidth: true + + visible: false + + clip: true + } + } + + color: "black" +} diff --git a/src/mainview/components/CallOverlay.qml b/src/mainview/components/CallOverlay.qml new file mode 100644 index 00000000..dfd599af --- /dev/null +++ b/src/mainview/components/CallOverlay.qml @@ -0,0 +1,381 @@ + +/* + * Copyright (C) 2020 by Savoir-faire Linux + * Author: Mingrui Zhang + * + * 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 . + */ +import QtQuick 2.14 +import QtQuick.Controls 2.14 +import QtQuick.Layouts 1.14 +import QtQuick.Controls.Universal 2.12 +import QtQml 2.14 +import net.jami.Models 1.0 + +import "../js/contactpickercreation.js" as ContactPickerCreation + +import "../../commoncomponents" + +Rectangle { + id: callOverlayRect + + property string bestName: "Best Name" + property string timeText: "00:00" + + signal backButtonIsClicked + signal overlayChatButtonClicked + + function updateButtonStatus(isPaused, isAudioOnly, isAudioMuted, isVideoMuted, isRecording, isSIP, isConferenceCall) { + callOverlayButtonGroup.setButtonStatus(isPaused, isAudioOnly, + isAudioMuted, isVideoMuted, + isRecording, isSIP, + isConferenceCall) + } + + function showOnHoldImage(visible) { + onHoldImage.visible = visible + } + + function closePotentialContactPicker() { + ContactPickerCreation.closeContactPicker() + } + + function setBackTintedButtonVisible(visible) { + backTintedButton.visible = visible + } + + anchors.fill: parent + + + /* + * Timer to decide when overlay fade out. + */ + Timer { + id: callOverlayTimer + interval: 5000 + onTriggered: { + if (overlayUpperPartRect.state !== 'freezed') { + overlayUpperPartRect.state = 'freezed' + } + if (callOverlayButtonGroup.state !== 'freezed') { + callOverlayButtonGroup.state = 'freezed' + } + } + } + + Rectangle { + id: overlayUpperPartRect + + anchors.top: callOverlayRect.top + + width: callOverlayRect.width + height: 50 + opacity: 0 + + RowLayout { + id: overlayUpperPartRectRowLayout + + anchors.fill: parent + + TintedButton { + id: backTintedButton + + Layout.alignment: Qt.AlignVCenter | Qt.AlignLeft + Layout.leftMargin: 5 + Layout.preferredWidth: 30 + Layout.preferredHeight: 30 + + tintColor: JamiTheme.buttonTintedBlue + normalPixmapSource: "qrc:/images/icons/ic_arrow_back_white_24dp.png" + selectedPixmapSource: "qrc:/images/icons/ic_arrow_back_white_24dp.png" + + onClicked: { + callOverlayRect.backButtonIsClicked() + } + + onButtonEntered: { + callOverlayRectMouseArea.entered() + } + } + + Text { + id: jamiBestNameText + + Layout.alignment: Qt.AlignVCenter | Qt.AlignLeft + Layout.preferredWidth: overlayUpperPartRect.width / 3 + Layout.preferredHeight: 50 + + font.pointSize: JamiTheme.textFontSize + + horizontalAlignment: Text.AlignHCenter + verticalAlignment: Text.AlignVCenter + + text: textMetricsjamiBestNameText.elidedText + color: "white" + + TextMetrics { + id: textMetricsjamiBestNameText + font: jamiBestNameText.font + text: bestName + elideWidth: overlayUpperPartRect.width / 3 + elide: Qt.ElideMiddle + } + } + + Text { + id: callTimerText + + Layout.alignment: Qt.AlignVCenter | Qt.AlignRight + Layout.preferredWidth: overlayUpperPartRect.width / 3 + Layout.preferredHeight: 50 + + font.pointSize: JamiTheme.textFontSize + + horizontalAlignment: Text.AlignHCenter + verticalAlignment: Text.AlignVCenter + + text: textMetricscallTimerText.elidedText + color: "white" + + TextMetrics { + id: textMetricscallTimerText + font: callTimerText.font + text: timeText + elideWidth: overlayUpperPartRect.width / 3 + elide: Qt.ElideMiddle + } + } + } + + color: "transparent" + + + /* + * Rect states: "entered" state should make overlay fade in, + * "freezed" state should make overlay fade out. + * Combine with PropertyAnimation of opacity. + */ + states: [ + State { + name: "entered" + PropertyChanges { + target: overlayUpperPartRect + opacity: 1 + } + }, + State { + name: "freezed" + PropertyChanges { + target: overlayUpperPartRect + opacity: 0 + } + } + ] + + transitions: Transition { + PropertyAnimation { + target: overlayUpperPartRect + property: "opacity" + duration: 1000 + } + } + } + + Image { + id: onHoldImage + + anchors.verticalCenter: callOverlayRect.verticalCenter + anchors.horizontalCenter: callOverlayRect.horizontalCenter + + width: 200 + height: 200 + + visible: false + + fillMode: Image.PreserveAspectFit + source: "qrc:/images/icons/ic_pause_white_100px.png" + asynchronous: true + } + + CallOverlayButtonGroup { + id: callOverlayButtonGroup + + anchors.bottom: callOverlayRect.bottom + anchors.bottomMargin: 10 + anchors.horizontalCenter: callOverlayRect.horizontalCenter + + width: callOverlayRect.width / 3 * 2 + height: 60 + opacity: 0 + + onChatButtonClicked: { + callOverlayRect.overlayChatButtonClicked() + } + + onAddToConferenceButtonClicked: { + + + /* + * Create contact picker - conference. + */ + ContactPickerCreation.createContactPickerObjects( + ContactPicker.ContactPickerType.JAMICONFERENCE, + callOverlayRect) + ContactPickerCreation.calculateCurrentGeo( + callOverlayRect.width / 2, callOverlayRect.height / 2) + ContactPickerCreation.openContactPicker() + } + + onTransferCallButtonClicked: { + + + /* + * Create contact picker - sip transfer. + */ + ContactPickerCreation.createContactPickerObjects( + ContactPicker.ContactPickerType.SIPTRANSFER, + callOverlayRect) + ContactPickerCreation.calculateCurrentGeo( + callOverlayRect.width / 2, callOverlayRect.height / 2) + ContactPickerCreation.openContactPicker() + } + + onButtonEntered: { + callOverlayRectMouseArea.entered() + } + + states: [ + State { + name: "entered" + PropertyChanges { + target: callOverlayButtonGroup + opacity: 1 + } + }, + State { + name: "freezed" + PropertyChanges { + target: callOverlayButtonGroup + opacity: 0 + } + } + ] + + transitions: Transition { + PropertyAnimation { + target: callOverlayButtonGroup + property: "opacity" + duration: 1000 + } + } + } + + + /* + * MouseAreas to make sure that overlay states are correctly set. + */ + MouseArea { + id: callOverlayButtonGroupLeftSideMouseArea + + anchors.bottom: callOverlayRect.bottom + anchors.left: callOverlayRect.left + + width: callOverlayRect.width / 6 + height: 60 + + hoverEnabled: true + propagateComposedEvents: true + acceptedButtons: Qt.NoButton + + onEntered: { + callOverlayRectMouseArea.entered() + } + + onMouseXChanged: { + callOverlayRectMouseArea.entered() + } + } + + MouseArea { + id: callOverlayButtonGroupRightSideMouseArea + + anchors.bottom: callOverlayRect.bottom + anchors.right: callOverlayRect.right + + width: callOverlayRect.width / 6 + height: 60 + + hoverEnabled: true + propagateComposedEvents: true + acceptedButtons: Qt.NoButton + + onEntered: { + callOverlayRectMouseArea.entered() + } + + onMouseXChanged: { + callOverlayRectMouseArea.entered() + } + } + + MouseArea { + id: callOverlayRectMouseArea + + anchors.top: callOverlayRect.top + anchors.topMargin: 50 + + width: callOverlayRect.width + height: callOverlayRect.height - callOverlayButtonGroup.height - 50 + + hoverEnabled: true + propagateComposedEvents: true + acceptedButtons: Qt.NoButton + + onEntered: { + if (overlayUpperPartRect.state !== 'entered') { + overlayUpperPartRect.state = 'entered' + } + if (callOverlayButtonGroup.state !== 'entered') { + callOverlayButtonGroup.state = 'entered' + } + callOverlayTimer.restart() + } + + onMouseXChanged: { + if (overlayUpperPartRect.state !== 'entered') { + overlayUpperPartRect.state = 'entered' + } + if (callOverlayButtonGroup.state !== 'entered') { + callOverlayButtonGroup.state = 'entered' + } + callOverlayTimer.restart() + } + } + + color: "transparent" + + onBestNameChanged: { + ContactAdapter.setCalleeDisplayName(bestName) + } + + onWidthChanged: { + ContactPickerCreation.calculateCurrentGeo(callOverlayRect.width / 2, + callOverlayRect.height / 2) + } + + onHeightChanged: { + ContactPickerCreation.calculateCurrentGeo(callOverlayRect.width / 2, + callOverlayRect.height / 2) + } +} diff --git a/src/mainview/components/CallOverlayButtonGroup.qml b/src/mainview/components/CallOverlayButtonGroup.qml new file mode 100644 index 00000000..4309fa1b --- /dev/null +++ b/src/mainview/components/CallOverlayButtonGroup.qml @@ -0,0 +1,311 @@ + +/* + * Copyright (C) 2020 by Savoir-faire Linux + * Author: Mingrui Zhang + * + * 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 . + */ +import QtQuick 2.14 +import QtQuick.Controls 2.14 +import QtQuick.Layouts 1.14 +import QtQuick.Controls.Universal 2.12 +import QtQml 2.14 +import net.jami.Models 1.0 + +import "../../commoncomponents" + +Rectangle { + id: callOverlayButtonGroupRect + + + /* + * ButtonCounts here is to make sure that flow layout margin is calculated correctly, + * since no other methods can make buttons at the layout center. + */ + property int buttonCounts: 9 + property int buttonPreferredSize: 30 + + signal buttonEntered + signal chatButtonClicked + signal addToConferenceButtonClicked + signal transferCallButtonClicked + + function setButtonStatus(isPaused, isAudioOnly, isAudioMuted, isVideoMuted, isRecording, isSIP, isConferenceCall) { + noVideoButton.visible = !isAudioOnly + addToConferenceButton.visible = !isSIP + transferCallButton.visible = isSIP + sipInputPanelButton.visible = isSIP + + noMicButton.setChecked(isAudioMuted) + noVideoButton.setChecked(isVideoMuted) + recButton.setChecked(isRecording) + holdButton.setChecked(isPaused) + + holdButton.visible = !isConferenceCall + } + + function calculateFlowMargin() { + return (callOverlayButtonGroupRect.width - buttonCounts * buttonPreferredSize + - callOverlayButtonGroupRectFlow.spacing * (buttonCounts - 1)) / 2 + } + + Flow { + id: callOverlayButtonGroupRectFlow + + anchors.fill: parent + + + /* + * Minus 1 is to make sure that button will not flick when doing flow layout. + */ + anchors.leftMargin: calculateFlowMargin( + ) < 0 ? 0 : calculateFlowMargin() - 1 + anchors.rightMargin: calculateFlowMargin( + ) < 0 ? 0 : calculateFlowMargin() - 1 + + spacing: 10 + + TintedButton { + id: hangUpButton + + width: buttonPreferredSize + height: buttonPreferredSize + + tintColor: JamiTheme.hangUpButtonTintedRed + normalPixmapSource: "qrc:/images/icons/ic_close_white_24dp.png" + selectedPixmapSource: "qrc:/images/icons/ic_close_white_24dp.png" + + onButtonEntered: { + callOverlayButtonGroupRect.buttonEntered() + } + + onClicked: { + CallAdapter.hangUpThisCall() + } + + onVisibleChanged: { + if (this.visible) + buttonCounts++ + else + buttonCounts-- + } + } + + TintedButton { + id: holdButton + + width: buttonPreferredSize + height: buttonPreferredSize + + tintColor: JamiTheme.buttonTintedBlue + normalPixmapSource: "qrc:/images/icons/ic_pause_white_24dp.png" + selectedPixmapSource: "qrc:/images/icons/ic_play_white_24dp.png" + + onClicked: { + CallAdapter.holdThisCallToggle() + } + + onButtonEntered: { + callOverlayButtonGroupRect.buttonEntered() + } + + onVisibleChanged: { + if (this.visible) + buttonCounts++ + else + buttonCounts-- + } + } + + TintedButton { + id: addToConferenceButton + + width: buttonPreferredSize + height: buttonPreferredSize + + tintColor: JamiTheme.buttonTintedBlue + normalPixmapSource: "qrc:/images/icons/ic_group_add_white_24dp.png" + selectedPixmapSource: "qrc:/images/icons/ic_group_add_white_24dp.png" + + onButtonEntered: { + callOverlayButtonGroupRect.buttonEntered() + } + + onClicked: { + callOverlayButtonGroupRect.addToConferenceButtonClicked() + } + + onVisibleChanged: { + if (this.visible) + buttonCounts++ + else + buttonCounts-- + } + } + + TintedButton { + id: transferCallButton + + width: buttonPreferredSize + height: buttonPreferredSize + + tintColor: JamiTheme.buttonTintedBlue + normalPixmapSource: "qrc:/images/icons/ic_call_transfer_white_24px.png" + selectedPixmapSource: "qrc:/images/icons/ic_call_transfer_white_24px.png" + + onButtonEntered: { + callOverlayButtonGroupRect.buttonEntered() + } + + onClicked: { + callOverlayButtonGroupRect.transferCallButtonClicked() + } + + onVisibleChanged: { + if (this.visible) + buttonCounts++ + else + buttonCounts-- + } + } + + TintedButton { + id: chatButton + + width: buttonPreferredSize + height: buttonPreferredSize + + tintColor: JamiTheme.buttonTintedBlue + normalPixmapSource: "qrc:/images/icons/ic_chat_white_24dp.png" + selectedPixmapSource: "qrc:/images/icons/ic_chat_white_24dp.png" + + onClicked: { + callOverlayButtonGroupRect.chatButtonClicked() + } + + onButtonEntered: { + callOverlayButtonGroupRect.buttonEntered() + } + + onVisibleChanged: { + if (this.visible) + buttonCounts++ + else + buttonCounts-- + } + } + + TintedButton { + id: noMicButton + + width: buttonPreferredSize + height: buttonPreferredSize + + tintColor: JamiTheme.buttonTintedBlue + normalPixmapSource: "qrc:/images/icons/ic_mic_white_24dp.png" + selectedPixmapSource: "qrc:/images/icons/ic_mic_off_white_24dp.png" + + onClicked: { + CallAdapter.muteThisCallToggle() + } + + onButtonEntered: { + callOverlayButtonGroupRect.buttonEntered() + } + + onVisibleChanged: { + if (this.visible) + buttonCounts++ + else + buttonCounts-- + } + } + + TintedButton { + id: noVideoButton + + width: buttonPreferredSize + height: buttonPreferredSize + + tintColor: JamiTheme.buttonTintedBlue + normalPixmapSource: "qrc:/images/icons/ic_videocam_white.png" + selectedPixmapSource: "qrc:/images/icons/ic_videocam_off_white_24dp.png" + + onButtonEntered: { + callOverlayButtonGroupRect.buttonEntered() + } + + onClicked: { + CallAdapter.videoPauseThisCallToggle() + } + + onVisibleChanged: { + if (this.visible) + buttonCounts++ + else + buttonCounts-- + } + } + + TintedButton { + id: recButton + + width: buttonPreferredSize + height: buttonPreferredSize + + tintColor: JamiTheme.buttonTintedBlue + normalPixmapSource: "qrc:/images/icons/ic_voicemail_white_24dp_2x.png" + selectedPixmapSource: "qrc:/images/icons/ic_voicemail_white_24dp_2x.png" + + onButtonEntered: { + callOverlayButtonGroupRect.buttonEntered() + } + + onClicked: { + CallAdapter.recordThisCallToggle() + } + + onVisibleChanged: { + if (this.visible) + buttonCounts++ + else + buttonCounts-- + } + } + + TintedButton { + id: sipInputPanelButton + + width: buttonPreferredSize + height: buttonPreferredSize + + tintColor: JamiTheme.buttonTintedBlue + normalPixmapSource: "qrc:/images/icons/icon-keypad-24-2x.png" + selectedPixmapSource: "qrc:/images/icons/icon-keypad-24-2x.png" + + onButtonEntered: { + callOverlayButtonGroupRect.buttonEntered() + } + + onVisibleChanged: { + if (this.visible) + buttonCounts++ + else + buttonCounts-- + } + } + } + + color: "transparent" +} diff --git a/src/mainview/components/CallStackView.qml b/src/mainview/components/CallStackView.qml new file mode 100644 index 00000000..61df06e3 --- /dev/null +++ b/src/mainview/components/CallStackView.qml @@ -0,0 +1,227 @@ + +/* + * Copyright (C) 2020 by Savoir-faire Linux + * Author: Mingrui Zhang + * + * 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 . + */ +import QtQuick 2.14 +import QtQuick.Window 2.14 +import QtQuick.Controls 2.14 +import QtQuick.Layouts 1.14 +import QtQuick.Controls.Universal 2.12 +import net.jami.Models 1.0 + +import "../js/incomingcallpagecreation.js" as IncomingCallPageCreation +import "../js/videocallfullscreenwindowcontainercreation.js" as VideoCallFullScreenWindowContainerCreation + +Rectangle { + id: callStackViewWindow + + anchors.fill: parent + + Shortcut { + sequence: "Ctrl+D" + context: Qt.ApplicationShortcut + onActivated: CallAdapter.hangUpThisCall() + } + + /* + * When selected conversation is changed, + * these values will also be changed. + */ + property string responsibleConvUid: "" + property string responsibleAccountId: "" + + signal outgoingCallPageBackButtonIsClicked + signal callPageBackButtonIsClicked + + function needToCloseInCallConversationAndPotentialWindow() { + audioCallPage.closeInCallConversation() + videoCallPage.closeInCallConversation() + + + /* + * Close potential window, context menu releated windows. + */ + audioCallPage.closeContextMenuAndRelatedWindows() + + VideoCallFullScreenWindowContainerCreation.closeVideoCallFullScreenWindowContainer() + videoCallPage.setCallOverlayBackButtonVisible(true) + videoCallPage.closeContextMenuAndRelatedWindows() + } + + function setCorrspondingMessageWebView(webViewId) { + audioCallPage.setAudioCallPageCorrspondingMessageWebView(webViewId) + videoCallPage.setVideoCallPageCorrspondingMessageWebView(webViewId) + } + + function updateCorrspondingUI() { + audioCallPage.updateUI(responsibleAccountId, responsibleConvUid) + outgoingCallPage.updateUI(responsibleAccountId, responsibleConvUid) + videoCallPage.updateUI(responsibleAccountId, responsibleConvUid) + } + + function showAudioCallPage() { + var itemToFind = callStackMainView.find(function (item) { + return item.stackNumber === 0 + }) + + if (!itemToFind) { + callStackMainView.push(audioCallPage, StackView.Immediate) + } else { + callStackMainView.pop(itemToFind, StackView.Immediate) + } + audioCallPage.updateUI(responsibleAccountId, responsibleConvUid) + } + + function showOutgoingCallPage(currentCallStatus) { + var itemToFind = callStackMainView.find(function (item) { + return item.stackNumber === 1 + }) + + if (!itemToFind) { + callStackMainView.push(outgoingCallPage, StackView.Immediate) + } else { + callStackMainView.pop(itemToFind, StackView.Immediate) + } + if (currentCallStatus) + outgoingCallPage.callStatusPresentation = currentCallStatus + } + + function showVideoCallPage(callId) { + var itemToFind = callStackMainView.find(function (item) { + return item.stackNumber === 2 + }) + + if (!itemToFind) { + callStackMainView.push(videoCallPage, StackView.Immediate) + } else { + callStackMainView.pop(itemToFind, StackView.Immediate) + } + videoCallPage.updateUI(responsibleAccountId, responsibleConvUid) + videoCallPage.setDistantRendererId(callId) + } + + Connections { + target: CallAdapter + + function onShowOutgoingCallPage(accountId, convUid) { + + + /* + * Need to check whether it is the current selected conversation. + */ + if (responsibleConvUid === convUid + && responsibleAccountId === accountId) { + showOutgoingCallPage() + } + } + + function onShowIncomingCallPage(accountId, convUid) { + + + /* + * Check is done within the js. + */ + IncomingCallPageCreation.createincomingCallPageWindowObjects( + accountId, convUid) + IncomingCallPageCreation.showIncomingCallPageWindow(accountId, + convUid) + } + + function onClosePotentialIncomingCallPageWindow(accountId, convUid) { + IncomingCallPageCreation.closeIncomingCallPageWindow(accountId, + convUid) + } + + function onShowAudioCallPage(accountId, convUid) { + if (responsibleConvUid === convUid + && responsibleAccountId === accountId) { + showAudioCallPage() + } + } + + function onShowVideoCallPage(accountId, convUid, callId) { + if (responsibleConvUid === convUid + && responsibleAccountId === accountId) { + showVideoCallPage(callId) + } + } + + function onCallStatusChanged(status, accountId, convUid) { + if (responsibleConvUid === convUid + && responsibleAccountId === accountId) { + outgoingCallPage.callStatusPresentation = status + } + } + } + + AudioCallPage { + id: audioCallPage + + property int stackNumber: 0 + + onAudioCallPageBackButtonIsClicked: { + callStackViewWindow.callPageBackButtonIsClicked() + } + } + + OutgoingCallPage { + id: outgoingCallPage + + property int stackNumber: 1 + + onCallCancelButtonIsClicked: { + CallAdapter.hangUpACall(responsibleAccountId, responsibleConvUid) + } + + onBackButtonIsClicked: { + callStackViewWindow.outgoingCallPageBackButtonIsClicked() + } + } + + VideoCallPage { + id: videoCallPage + + property int stackNumber: 2 + + onVideoCallPageBackButtonIsClicked: { + callStackViewWindow.callPageBackButtonIsClicked() + } + + onNeedToShowInFullScreen: { + VideoCallFullScreenWindowContainerCreation.createvideoCallFullScreenWindowContainerObject() + + if (!VideoCallFullScreenWindowContainerCreation.checkIfVisible()) { + VideoCallFullScreenWindowContainerCreation.setAsContainerChild( + videoCallPage) + videoCallPage.setCallOverlayBackButtonVisible(false) + VideoCallFullScreenWindowContainerCreation.showVideoCallFullScreenWindowContainer() + } else { + videoCallPage.parent = callStackMainView + videoCallPage.setCallOverlayBackButtonVisible(true) + VideoCallFullScreenWindowContainerCreation.closeVideoCallFullScreenWindowContainer() + } + } + } + + StackView { + id: callStackMainView + + anchors.fill: parent + + initialItem: outgoingCallPage + } +} diff --git a/src/mainview/components/ChangeLogScrollView.qml b/src/mainview/components/ChangeLogScrollView.qml new file mode 100644 index 00000000..f672e65d --- /dev/null +++ b/src/mainview/components/ChangeLogScrollView.qml @@ -0,0 +1,59 @@ + +/* + * Copyright (C) 2020 by Savoir-faire Linux + * Author: Mingrui Zhang + * + * 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 . + */ +import QtQuick 2.14 +import QtQuick.Controls 2.14 +import net.jami.Models 1.0 + +ScrollView { + id: changeLogScrollView + + anchors.fill: parent + + clip: true + + ScrollBar.horizontal.policy: ScrollBar.AlwaysOff + + TextEdit { + id: changeLogTextArea + + width: changeLogScrollView.width + + selectByMouse: false + readOnly: true + wrapMode: Text.WordWrap + + font.pointSize: JamiTheme.textFontSize - 3 + text: ClientWrapper.utilsAdaptor.getChangeLog() + textFormat: TextEdit.RichText + + MouseArea { + anchors.fill: parent + propagateComposedEvents: true + cursorShape: Qt.ArrowCursor + acceptedButtons: Qt.NoButton + } + } + + background: Rectangle { + id: changeLogScrollViewBackground + + radius: 5 + border.color: JamiTheme.tabbarBorderColor + } +} diff --git a/src/mainview/components/ContactPicker.qml b/src/mainview/components/ContactPicker.qml new file mode 100644 index 00000000..1d414062 --- /dev/null +++ b/src/mainview/components/ContactPicker.qml @@ -0,0 +1,149 @@ + +/* + * Copyright (C) 2020 by Savoir-faire Linux + * Author: Mingrui Zhang + * + * 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 . + */ +import QtQuick 2.14 +import QtQuick.Controls 2.14 +import QtQuick.Layouts 1.14 +import QtQuick.Controls.Universal 2.12 +import net.jami.Models 1.0 + +import "../../commoncomponents" + +Popup { + id: contactPickerPopup + + property int type: ContactPicker.ContactPickerType.JAMICONFERENCE + + + /* + * Important to keep it one, since enum in c++ starts at one for conferences. + */ + enum ContactPickerType { + JAMICONFERENCE = 1, + SIPTRANSFER + } + + contentWidth: 250 + contentHeight: contactPickerPopupRectColumnLayout.height + 50 + + padding: 0 + + modal: true + + contentItem: Rectangle { + id: contactPickerPopupRect + + width: 250 + + HoverableButton { + id: closeButton + + anchors.top: contactPickerPopupRect.top + anchors.topMargin: 5 + anchors.right: contactPickerPopupRect.right + anchors.rightMargin: 5 + + width: 30 + height: 30 + + radius: 30 + source: "qrc:/images/icons/ic_close_black_24dp.png" + + onClicked: { + contactPickerPopup.close() + } + } + + ColumnLayout { + id: contactPickerPopupRectColumnLayout + + anchors.top: contactPickerPopupRect.top + anchors.topMargin: 15 + + Text { + id: contactPickerTitle + + Layout.alignment: Qt.AlignCenter + Layout.preferredWidth: contactPickerPopupRect.width + Layout.preferredHeight: 30 + + font.pointSize: JamiTheme.textFontSize + font.bold: true + + horizontalAlignment: Text.AlignHCenter + verticalAlignment: Text.AlignVCenter + + text: type === ContactPicker.ContactPickerType.JAMICONFERENCE ? qsTr("Add to conference") : qsTr("Transfer this call") + } + + ContactSearchBar { + id: contactPickerContactSearchBar + + Layout.alignment: Qt.AlignCenter + Layout.topMargin: 5 + Layout.bottomMargin: 5 + Layout.preferredWidth: contactPickerPopupRect.width - 10 + Layout.preferredHeight: 35 + + onContactSearchBarTextChanged: { + ContactAdapter.setSearchFilter(text) + } + + Component.onCompleted: { + contactPickerContactSearchBar.setPlaceholderString( + qsTr("Search contacts")) + } + } + + ListView { + id: contactPickerListView + + Layout.alignment: Qt.AlignCenter + Layout.preferredWidth: contactPickerPopupRect.width + Layout.preferredHeight: 200 + + model: ContactAdapter.getContactSelectableModel(type) + + clip: true + + delegate: ContactPickerItemDelegate { + id: contactPickerItemDelegate + } + + ScrollIndicator.vertical: ScrollIndicator {} + } + } + + radius: 10 + color: "white" + } + + onAboutToShow: { + + + /* + * Reset the model on each show. + */ + contactPickerListView.model = ContactAdapter.getContactSelectableModel( + type) + } + + background: Rectangle { + color: "transparent" + } +} diff --git a/src/mainview/components/ContactPickerItemDelegate.qml b/src/mainview/components/ContactPickerItemDelegate.qml new file mode 100644 index 00000000..0f2f6568 --- /dev/null +++ b/src/mainview/components/ContactPickerItemDelegate.qml @@ -0,0 +1,135 @@ + +/* + * Copyright (C) 2020 by Savoir-faire Linux + * Author: Mingrui Zhang + * + * 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 . + */ +import QtQuick 2.14 +import QtQuick.Controls 2.14 +import QtQuick.Layouts 1.14 +import net.jami.Models 1.0 + +import "../../commoncomponents" + +ItemDelegate { + id: contactPickerItemDelegate + + Image { + id: contactPickerContactImage + + anchors.left: parent.left + anchors.verticalCenter: parent.verticalCenter + anchors.leftMargin: 10 + + width: 40 + height: 40 + + fillMode: Image.PreserveAspectFit + source: "data:image/png;base64," + Picture + mipmap: true + } + + Rectangle { + id: contactPickerContactInfoRect + + anchors.left: contactPickerContactImage.right + anchors.leftMargin: 10 + anchors.top: parent.top + + width: parent.width - contactPickerContactImage.width - 20 + height: parent.height + + color: "transparent" + + Text { + id: contactPickerContactName + + anchors.left: contactPickerContactInfoRect.left + anchors.bottom: contactPickerContactInfoRect.verticalCenter + + TextMetrics { + id: textMetricsContactPickerContactName + font: contactPickerContactName.font + elide: Text.ElideMiddle + elideWidth: contactPickerContactInfoRect.width + text: DisplayName + } + + text: textMetricsContactPickerContactName.elidedText + font.pointSize: JamiTheme.textFontSize + } + + Text { + id: contactPickerContactId + + anchors.left: contactPickerContactInfoRect.left + anchors.top: contactPickerContactInfoRect.verticalCenter + + fontSizeMode: Text.Fit + color: JamiTheme.faddedFontColor + + TextMetrics { + id: textMetricsContactPickerContactId + font: contactPickerContactId.font + elide: Text.ElideMiddle + elideWidth: contactPickerContactInfoRect.width + text: DisplayID == DisplayName ? "" : DisplayID + } + + text: textMetricsContactPickerContactId.elidedText + font.pointSize: JamiTheme.textFontSize + } + } + + background: Rectangle { + id: itemSmartListBackground + + color: "white" + + implicitWidth: contactPickerPopupRect.width + implicitHeight: Math.max( + contactPickerContactName.height + + textMetricsContactPickerContactId.height + 10, + contactPickerContactImage.height + 10) + border.width: 0 + } + + MouseArea { + id: mouseAreaContactPickerItemDelegate + + anchors.fill: parent + hoverEnabled: true + acceptedButtons: Qt.LeftButton + + onPressed: { + itemSmartListBackground.color = JamiTheme.pressColor + } + + onReleased: { + itemSmartListBackground.color = JamiTheme.releaseColor + + ContactAdapter.contactSelected(index) + contactPickerPopup.close() + } + + onEntered: { + itemSmartListBackground.color = JamiTheme.hoverColor + } + + onExited: { + itemSmartListBackground.color = "white" + } + } +} diff --git a/src/mainview/components/ContactSearchBar.qml b/src/mainview/components/ContactSearchBar.qml new file mode 100644 index 00000000..896b48c7 --- /dev/null +++ b/src/mainview/components/ContactSearchBar.qml @@ -0,0 +1,107 @@ + +/* + * Copyright (C) 2020 by Savoir-faire Linux + * Author: Mingrui Zhang + * + * 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 . + */ +import QtQuick 2.14 +import QtQuick.Controls 2.14 +import QtQuick.Layouts 1.14 +import net.jami.Models 1.0 + +Rectangle { + id: contactSearchBarRect + + signal contactSearchBarTextChanged(string text) + + function setPlaceholderString(str) { + placeholderTextForSearchBar.text = str + } + + + /* + * Hack - there is no real way now to make TextField lose its focus, + * unless transfer it to other component. + */ + function clearFocus() { + fakeFocus.forceActiveFocus() + } + + function clearText() { + contactSearchBar.clear() + fakeFocus.forceActiveFocus() + } + + border.color: JamiTheme.pressColor + radius: 10 + color: contactSearchBar.activeFocus ? "white" : JamiTheme.contactSearchBarPlaceHolderGreyBackground + + FocusScope { + id: fakeFocus + } + + Image { + id: searchIconImage + + anchors.verticalCenter: contactSearchBarRect.verticalCenter + anchors.left: contactSearchBarRect.left + anchors.leftMargin: 5 + + width: 20 + height: 20 + + fillMode: Image.PreserveAspectFit + mipmap: true + source: "qrc:/images/icons/ic_baseline-search-24px.svg" + } + + TextField { + id: contactSearchBar + + anchors.verticalCenter: contactSearchBarRect.verticalCenter + anchors.left: searchIconImage.right + + width: contactSearchBarRect.width - searchIconImage.width - 10 + height: contactSearchBarRect.height - 5 + + font.pointSize: JamiTheme.textFontSize - 1 + selectByMouse: true + selectionColor: JamiTheme.contactSearchBarPlaceHolderTextFontColor + + Text { + id: placeholderTextForSearchBar + + anchors.verticalCenter: contactSearchBar.verticalCenter + anchors.left: contactSearchBar.left + anchors.leftMargin: 5 + + text: qsTr("Find or start a conversation") + font.pointSize: JamiTheme.textFontSize - 1 + color: JamiTheme.contactSearchBarPlaceHolderTextFontColor + visible: !contactSearchBar.text && !contactSearchBar.activeFocus + } + + background: Rectangle { + id: searchBarBackground + + color: "transparent" + } + + onTextChanged: { + contactSearchBarRect.contactSearchBarTextChanged( + contactSearchBar.text) + } + } +} diff --git a/src/mainview/components/ConversationSmartListContextMenu.qml b/src/mainview/components/ConversationSmartListContextMenu.qml new file mode 100644 index 00000000..aece4b46 --- /dev/null +++ b/src/mainview/components/ConversationSmartListContextMenu.qml @@ -0,0 +1,151 @@ + +/* + * Copyright (C) 2020 by Savoir-faire Linux + * Author: Mingrui Zhang + * + * 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 . + */ +import QtQuick 2.14 +import QtQuick.Controls 2.14 +import net.jami.Models 1.0 + +import "../../commoncomponents" + +Menu { + id: contextMenu + + property string responsibleAccountId: "" + property string responsibleConvUid: "" + + property int generalMenuSeparatorCount: 0 + property int commonBorderWidth: 2 + + + /* + * All GeneralMenuItems should remain the same width / height. + */ + GeneralMenuItem { + id: startVideoCallItem + + itemName: qsTr("Start video call") + topBorderWidth: commonBorderWidth + leftBorderWidth: commonBorderWidth + rightBorderWidth: commonBorderWidth + + onClicked: { + contextMenu.close() + ConversationsAdapter.selectConversation(responsibleAccountId, + responsibleConvUid, false) + CallAdapter.placeCall() + } + } + + GeneralMenuItem { + id: startAudioCallItem + + itemName: qsTr("Start audio call") + leftBorderWidth: commonBorderWidth + rightBorderWidth: commonBorderWidth + + onClicked: { + contextMenu.close() + ConversationsAdapter.selectConversation(responsibleAccountId, + responsibleConvUid, false) + CallAdapter.placeAudioOnlyCall() + } + } + + GeneralMenuItem { + id: clearConversationItem + + itemName: qsTr("Clear conversation") + leftBorderWidth: commonBorderWidth + rightBorderWidth: commonBorderWidth + + onClicked: { + contextMenu.close() + ClientWrapper.utilsAdaptor.clearConversationHistory(responsibleAccountId, + responsibleConvUid) + } + } + + GeneralMenuItem { + id: removeContactItem + + itemName: qsTr("Remove contact") + leftBorderWidth: commonBorderWidth + rightBorderWidth: commonBorderWidth + + onClicked: { + contextMenu.close() + ClientWrapper.utilsAdaptor.removeConversation(responsibleAccountId, + responsibleConvUid) + } + } + + GeneralMenuSeparator { + preferredWidth: startVideoCallItem.preferredWidth + preferredHeight: commonBorderWidth + + Component.onCompleted: { + generalMenuSeparatorCount++ + } + } + + GeneralMenuItem { + id: blockContactItem + + itemName: qsTr("Block contact") + leftBorderWidth: commonBorderWidth + rightBorderWidth: commonBorderWidth + + onClicked: { + contextMenu.close() + ClientWrapper.utilsAdaptor.removeConversation(responsibleAccountId, + responsibleConvUid, true) + } + } + + GeneralMenuSeparator { + preferredWidth: startVideoCallItem.preferredWidth + preferredHeight: commonBorderWidth + + Component.onCompleted: { + generalMenuSeparatorCount++ + } + } + + GeneralMenuItem { + id: profileItem + + itemName: qsTr("Profile") + bottomBorderWidth: commonBorderWidth + leftBorderWidth: commonBorderWidth + rightBorderWidth: commonBorderWidth + + onClicked: { + contextMenu.close() + userProfile.open() + } + } + + background: Rectangle { + implicitWidth: startVideoCallItem.preferredWidth + implicitHeight: startVideoCallItem.preferredHeight + * (contextMenu.count - generalMenuSeparatorCount) + + border.width: commonBorderWidth + border.color: JamiTheme.tabbarBorderColor + } +} diff --git a/src/mainview/components/ConversationSmartListUserImage.qml b/src/mainview/components/ConversationSmartListUserImage.qml new file mode 100644 index 00000000..6419ec4e --- /dev/null +++ b/src/mainview/components/ConversationSmartListUserImage.qml @@ -0,0 +1,88 @@ + +/* + * Copyright (C) 2020 by Savoir-faire Linux + * Author: Mingrui Zhang + * + * 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 . + */ +import QtQuick 2.14 +import QtQuick.Controls 2.14 +import QtQuick.Layouts 1.14 +import net.jami.Models 1.0 + +Image { + id: userImage + + width: 50 + height: 50 + + fillMode: Image.PreserveAspectFit + source: "data:image/png;base64," + Picture + mipmap: true + + Rectangle { + id: presenseRect + + anchors.right: userImage.right + anchors.rightMargin: 1 + anchors.bottom: userImage.bottom + anchors.bottomMargin: 2 + + width: 14 + height: 14 + + visible: Presence + + Rectangle { + id: presenseCycle + + anchors.centerIn: presenseRect + + width: 10 + height: 10 + + radius: 30 + color: JamiTheme.presenceGreen + } + + radius: 30 + color: "white" + } + + Rectangle { + id: unreadMessageCountRect + + anchors.right: userImage.right + anchors.rightMargin: 1 + anchors.top: userImage.top + anchors.topMargin: 2 + + width: 14 + height: 14 + + visible: UnreadMessagesCount > 0 + + Text { + id: unreadMessageCounttext + + anchors.centerIn: unreadMessageCountRect + + text: UnreadMessagesCount > 9 ? "···" : UnreadMessagesCount + color: "white" + } + + radius: 30 + color: JamiTheme.notificationRed + } +} diff --git a/src/mainview/components/ConversationSmartListView.qml b/src/mainview/components/ConversationSmartListView.qml new file mode 100644 index 00000000..0513f6fd --- /dev/null +++ b/src/mainview/components/ConversationSmartListView.qml @@ -0,0 +1,104 @@ + +/* + * Copyright (C) 2020 by Savoir-faire Linux + * Author: Mingrui Zhang + * + * 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 . + */ +import QtQuick 2.14 +import QtQuick.Controls 2.14 +import QtQuick.Layouts 1.14 +import net.jami.Models 1.0 + +ListView { + id: conversationSmartListView + + signal needToAccessMessageWebView(string currentUserDisplayName, string currentUserAlias, string currentUID, bool callStackViewShouldShow, bool isAudioOnly, string callStateStr) + signal needToSelectItems(int index) + signal needToDeselectItems + signal needToBackToWelcomePage + signal needToGrabFocus + + signal needToShowChatView(string accountId, string convUid) + signal currentIndexIsChanged + signal forceUpdatePotentialInvalidItem + + + /* + * When model is sorted, we need to reset to focus (currentIndex) + * to the real conversation that we focused. + */ + function modelSorted(contactURIToCompare) { + var conversationSmartListViewModel = conversationSmartListView.model + conversationSmartListView.currentIndex = -1 + updateConversationSmartListView() + for (var i = 0; i < count; i++) { + if (conversationSmartListViewModel.data( + conversationSmartListViewModel.index(i, 0), + 261) === contactURIToCompare) { + conversationSmartListView.currentIndex = i + break + } + } + } + + + /* + * Refresh all item within model. + */ + function updateConversationSmartListView() { + var conversationSmartListViewModel = conversationSmartListView.model + conversationSmartListViewModel.dataChanged( + conversationSmartListViewModel.index(0, 0), + conversationSmartListViewModel.index( + conversationSmartListViewModel.rowCount() - 1, 0)) + conversationSmartListView.forceUpdatePotentialInvalidItem() + } + + function setModel(model) { + conversationSmartListView.model = model + } + + function backToWelcomePage() { + conversationSmartListView.needToBackToWelcomePage() + } + + + /* + * Update smartlist to accountId. + */ + function updateSmartList(accountId) { + conversationSmartListView.model.setAccount(accountId) + } + + Connections { + target: CallAdapter + + function onUpdateConversationSmartList() { + updateConversationSmartListView() + } + } + + onCurrentIndexChanged: { + conversationSmartListView.currentIndexIsChanged() + } + + clip: true + + delegate: ConversationSmartListViewItemDelegate { + id: smartListItemDelegate + } + + ScrollIndicator.vertical: ScrollIndicator {} +} diff --git a/src/mainview/components/ConversationSmartListViewItemDelegate.qml b/src/mainview/components/ConversationSmartListViewItemDelegate.qml new file mode 100644 index 00000000..7a766f06 --- /dev/null +++ b/src/mainview/components/ConversationSmartListViewItemDelegate.qml @@ -0,0 +1,280 @@ + +/* + * Copyright (C) 2020 by Savoir-faire Linux + * Author: Mingrui Zhang + * + * 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 . + */ +import QtQuick 2.14 +import QtQuick.Controls 2.14 +import QtQuick.Layouts 1.14 +import net.jami.Models 1.0 + +import "../../commoncomponents" + +ItemDelegate { + id: smartListItemDelegate + + Connections { + target: conversationSmartListView + + + /* + * Hack, make sure that smartListItemDelegate does not show extra item + * when searching new contacts. + */ + function onForceUpdatePotentialInvalidItem() { + smartListItemDelegate.visible = conversationSmartListView.model.rowCount( + ) <= index ? false : true + } + + + /* + * When currentIndex is -1, deselect items, if not, change select item + */ + function onCurrentIndexIsChanged() { + if (conversationSmartListView.currentIndex === -1 + || conversationSmartListView.currentIndex !== index) { + itemSmartListBackground.color = Qt.binding(function () { + return InCall ? Qt.lighter(JamiTheme.selectionBlue, + 1.8) : "white" + }) + } else { + itemSmartListBackground.color = Qt.binding(function () { + return InCall ? Qt.lighter(JamiTheme.selectionBlue, + 1.8) : JamiTheme.releaseColor + }) + } + } + + function onNeedToShowChatView(accountId, convUid) { + if (convUid === UID) { + conversationSmartListView.needToAccessMessageWebView( + DisplayID == DisplayName ? "" : DisplayID, + DisplayName, UID, CallStackViewShouldShow, + IsAudioOnly, CallStateStr) + } + } + } + + ConversationSmartListUserImage { + id: conversationSmartListUserImage + + anchors.left: parent.left + anchors.verticalCenter: parent.verticalCenter + anchors.leftMargin: 10 + } + + Rectangle { + id: conversationSmartListUserInfoRect + + anchors.left: conversationSmartListUserImage.right + anchors.leftMargin: 10 + anchors.top: parent.top + + width: LastInteractionDate ? (parent.width - conversationSmartListUserImage.width - 20) + / 2 : parent.width - conversationSmartListUserImage.width - 20 + height: parent.height + + color: "transparent" + + ColumnLayout { + id: conversationSmartListUserInfoColumnLayout + + anchors.fill: parent + + Text { + id: conversationSmartListUserName + + Layout.alignment: Qt.AlignLeft + + TextMetrics { + id: textMetricsConversationSmartListUserName + font: conversationSmartListUserName.font + elide: Text.ElideMiddle + elideWidth: conversationSmartListUserInfoRect.width + text: DisplayName + } + + text: textMetricsConversationSmartListUserName.elidedText + font.pointSize: JamiTheme.textFontSize + } + + Text { + id: conversationSmartListUserId + + Layout.alignment: Qt.AlignLeft + + fontSizeMode: Text.Fit + color: JamiTheme.faddedFontColor + + TextMetrics { + id: textMetricsConversationSmartListUserId + font: conversationSmartListUserId.font + elide: Text.ElideMiddle + elideWidth: conversationSmartListUserInfoRect.width + text: DisplayID == DisplayName ? "" : DisplayID + } + + text: textMetricsConversationSmartListUserId.elidedText + font.pointSize: JamiTheme.textFontSize + } + } + } + + Rectangle { + id: conversationSmartListUserLastInteractionRect + + anchors.left: conversationSmartListUserInfoRect.right + anchors.top: parent.top + + width: (parent.width - conversationSmartListUserImage.width - 20) / 2 - 10 + height: parent.height + + color: "transparent" + + ColumnLayout { + id: conversationSmartListUserLastInteractionColumnLayout + + anchors.fill: parent + + Text { + id: conversationSmartListUserLastInteractionDate + + Layout.alignment: Qt.AlignRight + + TextMetrics { + id: textMetricsConversationSmartListUserLastInteractionDate + font: conversationSmartListUserLastInteractionDate.font + elideWidth: conversationSmartListUserLastInteractionRect.width + elide: Text.ElideRight + text: LastInteractionDate + } + + text: textMetricsConversationSmartListUserLastInteractionDate.elidedText + font.pointSize: JamiTheme.textFontSize + color: JamiTheme.faddedFontColor + } + + Text { + id: conversationSmartListUserLastInteractionMessage + + Layout.alignment: Qt.AlignRight + + fontSizeMode: Text.Fit + + TextMetrics { + id: textMetricsConversationSmartListUserLastInteractionMessage + font: conversationSmartListUserLastInteractionMessage.font + elideWidth: conversationSmartListUserLastInteractionRect.width + elide: Text.ElideRight + text: InCall ? CallStateStr : (Draft ? Draft : LastInteraction) + } + + font.family: "Segoe UI Emoji" + font.hintingPreference: Font.PreferNoHinting + text: textMetricsConversationSmartListUserLastInteractionMessage.elidedText + font.pointSize: JamiTheme.textFontSize + color: Draft ? JamiTheme.draftRed : JamiTheme.faddedLastInteractionFontColor + } + } + } + + background: Rectangle { + id: itemSmartListBackground + + color: InCall ? Qt.lighter(JamiTheme.selectionBlue, 1.8) : "white" + + implicitWidth: conversationSmartListView.width + implicitHeight: Math.max( + conversationSmartListUserName.height + + textMetricsConversationSmartListUserId.height + 10, + conversationSmartListUserImage.height + 10) + border.width: 0 + } + + MouseArea { + id: mouseAreaSmartListItemDelegate + + anchors.fill: parent + hoverEnabled: true + acceptedButtons: Qt.LeftButton | Qt.RightButton + + onPressed: { + if (!InCall) { + itemSmartListBackground.color = JamiTheme.pressColor + } + } + onDoubleClicked: { + if (!InCall) { + ConversationsAdapter.selectConversation(ClientWrapper.utilsAdaptor.getCurrAccId(), + UID, false) + CallAdapter.placeCall() + } + } + onReleased: { + if (!InCall) { + itemSmartListBackground.color = JamiTheme.releaseColor + } + if (mouse.button === Qt.RightButton) { + + + /* + * Make menu pos at mouse. + */ + var relativeMousePos = mapToItem(itemSmartListBackground, + mouse.x, mouse.y) + smartListContextMenu.x = relativeMousePos.x + smartListContextMenu.y = relativeMousePos.y + smartListContextMenu.responsibleAccountId = ClientWrapper.utilsAdaptor.getCurrAccId() + smartListContextMenu.responsibleConvUid = UID + userProfile.responsibleConvUid = UID + userProfile.aliasText = DisplayName + userProfile.registeredNameText = DisplayID + userProfile.idText = URI + userProfile.contactPicBase64 = Picture + smartListContextMenu.open() + } else if (mouse.button === Qt.LeftButton) { + conversationSmartListView.currentIndex = index + conversationSmartListView.needToSelectItems(index) + conversationSmartListView.needToGrabFocus() + } + } + onEntered: { + if (!InCall) { + itemSmartListBackground.color = JamiTheme.hoverColor + } + } + onExited: { + if (!InCall) { + if (conversationSmartListView.currentIndex !== index + || conversationSmartListView.currentIndex === -1) { + itemSmartListBackground.color = Qt.binding(function () { + return InCall ? Qt.lighter(JamiTheme.selectionBlue, + 1.8) : "white" + }) + } else { + itemSmartListBackground.color = Qt.binding(function () { + return InCall ? Qt.lighter(JamiTheme.selectionBlue, + 1.8) : JamiTheme.releaseColor + }) + } + } + } + } + + ConversationSmartListContextMenu { + id: smartListContextMenu + } +} diff --git a/src/mainview/components/IncomingCallPage.qml b/src/mainview/components/IncomingCallPage.qml new file mode 100644 index 00000000..eafbaffe --- /dev/null +++ b/src/mainview/components/IncomingCallPage.qml @@ -0,0 +1,342 @@ + +/* + * Copyright (C) 2020 by Savoir-faire Linux + * Author: Mingrui Zhang + * + * 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 . + */ +import QtQuick 2.14 +import QtQuick.Window 2.14 +import QtQuick.Controls 2.14 +import QtQuick.Layouts 1.14 +import QtQuick.Controls.Universal 2.12 +import net.jami.Models 1.0 + +import "../../commoncomponents" + + +/* + * IncomingCallPage as a seperate window, + * exist at the right bottom, as a notification to user that + * a call is incoming. + */ +Window { + id: incomingCallPage + + property int minWidth: 300 + property int minHeight: 400 + + + /* + * The unique identifier for incomingCallPage + */ + property string responsibleAccountId: "" + property string responsibleConvUid: "" + + property string contactImgSource: "" + property string bestName: "Best Name" + property string bestId: "Best Id" + + property int buttonPreferredSize: 50 + property variant clickPos: "1,1" + + function updateUI() { + incomingCallPage.contactImgSource = "data:image/png;base64," + + ClientWrapper.utilsAdaptor.getContactImageString(responsibleAccountId, + responsibleConvUid) + incomingCallPage.bestName = ClientWrapper.utilsAdaptor.getBestName( + responsibleAccountId, responsibleConvUid) + var id = ClientWrapper.utilsAdaptor.getBestId(responsibleAccountId, + responsibleConvUid) + incomingCallPage.bestId = (incomingCallPage.bestName !== id) ? id : "" + } + + function updatePositionToRightBottom() { + + + /* + * Screen right bottom, + * since the qt screen.virtualY, virtualX does not work properly, + * we need to calculate the screen x, y ourselves, by + * using to fact that window will always be in the middle if no x or y + * specificed. + * ex: https://doc.qt.io/qt-5/qscreen.html#geometry-prop + */ + var virtualX = (incomingCallPage.x + width / 2) - screen.width / 2 + incomingCallPage.x = virtualX + screen.width - width + incomingCallPage.y = screen.height - height - 50 + } + + minimumWidth: minWidth + minimumHeight: minHeight + + maximumWidth: minWidth + 300 + maximumHeight: minHeight + 300 + + flags: Qt.FramelessWindowHint | Qt.WindowStaysOnTopHint + screen: Qt.application.screens[0] + + Rectangle { + id: incomingCallPageColumnLayoutMainRect + + anchors.fill: parent + + radius: 15 + color: "black" + + + /* + * Simulate window drag. (top with height 30). + */ + MouseArea { + id: dragMouseArea + + anchors.left: incomingCallPageColumnLayoutMainRect.left + anchors.top: incomingCallPageColumnLayoutMainRect.top + + width: incomingCallPageColumnLayoutMainRect.width - closeButton.width - 10 + height: 30 + + onPressed: { + clickPos = Qt.point(mouse.x, mouse.y) + } + + onPositionChanged: { + var delta = Qt.point(mouse.x - clickPos.x, mouse.y - clickPos.y) + incomingCallPage.x += delta.x + incomingCallPage.y += delta.y + } + } + + HoverableButton { + id: closeButton + + anchors.top: incomingCallPageColumnLayoutMainRect.top + anchors.topMargin: 10 + anchors.right: incomingCallPageColumnLayoutMainRect.right + anchors.rightMargin: 10 + + width: 30 + height: 30 + + radius: 30 + source: "qrc:/images/icons/ic_close_white_24dp.png" + backgroundColor: "black" + onEnterColor: JamiTheme.closeButtonLighterBlack + onExitColor: "black" + onPressColor: JamiTheme.declineButtonPressedRed + onReleaseColor: "black" + + onClicked: { + incomingCallPage.close() + CallAdapter.refuseACall(responsibleAccountId, + responsibleConvUid) + } + } + + ColumnLayout { + id: incomingCallPageColumnLayout + + anchors.fill: parent + + Image { + id: contactImg + + Layout.alignment: Qt.AlignCenter + Layout.topMargin: 30 + + Layout.preferredWidth: 100 + Layout.preferredHeight: 100 + + fillMode: Image.PreserveAspectFit + source: contactImgSource + } + + Rectangle { + id: incomingCallPageTextRect + + Layout.alignment: Qt.AlignCenter + Layout.topMargin: 5 + + Layout.preferredWidth: incomingCallPage.width + Layout.preferredHeight: jamiBestNameText.height + jamiBestIdText.height + + talkToYouText.height + 20 + + ColumnLayout { + id: incomingCallPageTextRectColumnLayout + + Text { + id: jamiBestNameText + + Layout.alignment: Qt.AlignCenter + Layout.preferredWidth: incomingCallPageTextRect.width + Layout.preferredHeight: 50 + + font.pointSize: JamiTheme.textFontSize + 3 + + horizontalAlignment: Text.AlignHCenter + verticalAlignment: Text.AlignVCenter + + text: textMetricsjamiBestNameText.elidedText + color: "white" + + TextMetrics { + id: textMetricsjamiBestNameText + font: jamiBestNameText.font + text: bestName + elideWidth: incomingCallPageTextRect.width - 30 + elide: Qt.ElideMiddle + } + } + + Text { + id: jamiBestIdText + + Layout.alignment: Qt.AlignCenter + Layout.preferredWidth: incomingCallPageTextRect.width + Layout.preferredHeight: 30 + + font.pointSize: JamiTheme.textFontSize + + horizontalAlignment: Text.AlignHCenter + verticalAlignment: Text.AlignVCenter + + text: textMetricsjamiBestIdText.elidedText + color: "white" + + TextMetrics { + id: textMetricsjamiBestIdText + font: jamiBestIdText.font + text: bestId + elideWidth: incomingCallPageTextRect.width - 30 + elide: Qt.ElideMiddle + } + } + + Text { + id: talkToYouText + + Layout.alignment: Qt.AlignCenter + Layout.preferredWidth: incomingCallPageTextRect.width + Layout.preferredHeight: 30 + + font.pointSize: JamiTheme.textFontSize + + horizontalAlignment: Text.AlignHCenter + verticalAlignment: Text.AlignVCenter + color: "white" + + text: "is calling you" + } + } + + color: "transparent" + } + + RowLayout { + id: incomingCallPageRowLayout + + Layout.alignment: Qt.AlignHCenter | Qt.AlignBottom + Layout.bottomMargin: 5 + + Layout.preferredWidth: incomingCallPage.width - 100 + Layout.preferredHeight: buttonPreferredSize + + ColumnLayout { + id: callAnswerButtonColumnLayout + + Layout.alignment: Qt.AlignLeft + + HoverableButton { + id: callAnswerButton + + Layout.alignment: Qt.AlignCenter + + Layout.preferredWidth: buttonPreferredSize + Layout.preferredHeight: buttonPreferredSize + + backgroundColor: JamiTheme.acceptButtonGreen + onEnterColor: JamiTheme.acceptButtonHoverGreen + onPressColor: JamiTheme.acceptButtonPressedGreen + onReleaseColor: JamiTheme.acceptButtonHoverGreen + onExitColor: JamiTheme.acceptButtonGreen + + buttonImageHeight: buttonPreferredSize / 2 + buttonImageWidth: buttonPreferredSize / 2 + source: "qrc:/images/icons/ic_check_white_18dp_2x.png" + radius: 30 + + onClicked: { + incomingCallPage.close() + CallAdapter.acceptACall(responsibleAccountId, + responsibleConvUid) + } + } + + Text { + id: answerText + + Layout.alignment: Qt.AlignCenter + + font.pointSize: JamiTheme.textFontSize - 2 + text: qsTr("Answer") + } + } + + ColumnLayout { + id: callDeclineButtonColumnLayout + + Layout.alignment: Qt.AlignRight + + HoverableButton { + id: callDeclineButton + + Layout.alignment: Qt.AlignCenter + + Layout.preferredWidth: buttonPreferredSize + Layout.preferredHeight: buttonPreferredSize + + backgroundColor: JamiTheme.declineButtonRed + onEnterColor: JamiTheme.declineButtonHoverRed + onPressColor: JamiTheme.declineButtonPressedRed + onReleaseColor: JamiTheme.declineButtonHoverRed + onExitColor: JamiTheme.declineButtonRed + + buttonImageHeight: buttonPreferredSize / 2 + buttonImageWidth: buttonPreferredSize / 2 + source: "qrc:/images/icons/ic_close_white_24dp.png" + radius: 30 + + onClicked: { + incomingCallPage.close() + CallAdapter.refuseACall(responsibleAccountId, + responsibleConvUid) + } + } + + Text { + id: ignoreText + + Layout.alignment: Qt.AlignCenter + + font.pointSize: JamiTheme.textFontSize - 2 + text: qsTr("Ignore") + } + } + } + } + } + + color: "transparent" +} diff --git a/src/mainview/components/MessageWebView.qml b/src/mainview/components/MessageWebView.qml new file mode 100644 index 00000000..2045edf8 --- /dev/null +++ b/src/mainview/components/MessageWebView.qml @@ -0,0 +1,293 @@ + +/* + * Copyright (C) 2020 by Savoir-faire Linux + * Author: Mingrui Zhang + * + * 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 . + */ +import QtQuick 2.14 +import QtQuick.Controls 2.14 +import QtQuick.Layouts 1.14 +import QtWebEngine 1.10 +import QtWebChannel 1.14 +import net.jami.Models 1.0 + +import "../../commoncomponents" + + +Rectangle { + id: messageWebViewRect + + property int messageWebViewHeaderPreferredHeight: 60 + property string headerUserAliasLabelText: "" + property string headerUserUserNameLabelText: "" + + signal needToGoBackToWelcomeView + signal needToHideConversationInCall + signal needToSendContactRequest + + signal sendMessageContentSaved(string arg) + signal messagesCleared + signal messagesLoaded + + + function webViewRunJavaScript(arg) { + messageWebView.runJavaScript(arg) + } + + function setSendContactRequestButtonVisible(visible) { + messageWebViewHeader.sendContactRequestButtonVisible = visible + } + + function setMessagingHeaderButtonsVisible(visible) { + messageWebViewHeader.toggleMessagingHeaderButtonsVisible(visible) + } + + function resetMessagingHeaderBackButtonSource(reset) { + messageWebViewHeader.resetBackToWelcomeViewButtonSource(reset) + } + + anchors.fill: parent + + JamiFileDialog { + id: jamiFileDialog + + mode: JamiFileDialog.Mode.OpenFiles + + onAccepted: { + var filePaths = jamiFileDialog.files + for (var index = 0; index < filePaths.length; ++index) { + var path = ClientWrapper.utilsAdaptor.getAbsPath(filePaths[index]) + MessagesAdapter.setNewMessagesContent(path) + } + } + } + + MessageWebViewHeader { + + DropArea{ + anchors.fill: parent + onDropped: { + var path = ClientWrapper.utilsAdaptor.getAbsPath(drop.text.toString()) + MessagesAdapter.setNewMessagesContent(path) + } + } + + id: messageWebViewHeader + + anchors.top: messageWebViewRect.top + anchors.left: messageWebViewRect.left + + width: messageWebViewRect.width + height: messageWebViewHeaderPreferredHeight + + userAliasLabelText: headerUserAliasLabelText + userUserNameLabelText: headerUserUserNameLabelText + + onBackToWelcomeViewButtonClicked: { + MessagesAdapter.updateDraft() + messageWebViewRect.needToGoBackToWelcomeView() + } + + onNeedToHideConversationInCall: { + messageWebViewRect.needToHideConversationInCall() + } + + onSendContactRequestButtonClicked: { + MessagesAdapter.sendContactRequest() + } + } + + QtObject { + id: jsBridgeObject + + + /* + * ID, under which this object will be known at chatview.js side. + */ + WebChannel.id: "jsbridge" + + + /* + * Functions that are exposed, return code can be derived from js side + * by setting callback function. + */ + function deleteInteraction(arg) { + MessagesAdapter.deleteInteraction(arg) + } + + function retryInteraction(arg) { + MessagesAdapter.retryInteraction(arg) + } + + function openFile(arg) { + MessagesAdapter.openFile(arg) + } + + function acceptFile(arg) { + MessagesAdapter.acceptFile(arg) + } + + function refuseFile(arg) { + MessagesAdapter.refuseFile(arg) + } + + function sendMessage(arg) { + MessagesAdapter.sendMessage(arg) + } + + function sendImage(arg) { + MessagesAdapter.sendImage(arg) + } + + function sendFile(arg) { + MessagesAdapter.sendFile(arg) + } + + function selectFile() { + jamiFileDialog.open() + } + + function acceptInvitation() { + MessagesAdapter.acceptInvitation() + } + + function refuseInvitation() { + MessagesAdapter.refuseInvitation() + } + + function blockConversation() { + MessagesAdapter.blockConversation() + } + + function emitMessagesCleared() { + messageWebViewRect.messagesCleared() + } + + function emitMessagesLoaded() { + messageWebViewRect.messagesLoaded() + } + + function emitPasteKeyDetected() { + MessagesAdapter.pasteKeyDetected() + } + + function openAudioRecorder(spikePosX, spikePosY) { + recordBox.openRecorder(spikePosX, spikePosY, false) + } + + function openVideoRecorder(spikePosX, spikePosY) { + recordBox.openRecorder(spikePosX, spikePosY, true) + } + + function saveSendMessageContent(arg) { + messageWebViewRect.sendMessageContentSaved(arg) + } + + function onComposing(isComposing) { + MessagesAdapter.onComposing(isComposing) + } + } + + WebEngineView { + + id: messageWebView + + anchors.top: messageWebViewHeader.bottom + anchors.topMargin: 1 + anchors.left: messageWebViewRect.left + + width: messageWebViewRect.width + height: messageWebViewRect.height - messageWebViewHeaderPreferredHeight + + settings.javascriptEnabled: true + settings.javascriptCanOpenWindows: true + settings.fullScreenSupportEnabled: true + settings.allowRunningInsecureContent: true + settings.localContentCanAccessRemoteUrls: true + settings.localContentCanAccessFileUrls: true + settings.errorPageEnabled: false + settings.pluginsEnabled: false + settings.screenCaptureEnabled: false + settings.linksIncludedInFocusChain: false + settings.localStorageEnabled: false + + webChannel: messageWebViewChannel + profile: messageWebViewProfile + + DropArea{ + anchors.fill: parent + onDropped: { + var path = ClientWrapper.utilsAdaptor.getAbsPath(drop.text.toString()) + MessagesAdapter.setNewMessagesContent(path) + } + } + + onLoadingChanged: { + if (loadRequest.status == WebEngineView.LoadSucceededStatus) { + messageWebView.runJavaScript(ClientWrapper.utilsAdaptor.getStyleSheet( + "chatcss", + ClientWrapper.utilsAdaptor.qStringFromFile( + ":/chatview.css"))) + messageWebView.runJavaScript(ClientWrapper.utilsAdaptor.getStyleSheet( + "chatwin", + ClientWrapper.utilsAdaptor.qStringFromFile( + ":/chatview-windows.css"))) + + messageWebView.runJavaScript(ClientWrapper.utilsAdaptor.qStringFromFile( + ":/jed.js")) + messageWebView.runJavaScript(ClientWrapper.utilsAdaptor.qStringFromFile( + ":/linkify.js")) + messageWebView.runJavaScript(ClientWrapper.utilsAdaptor.qStringFromFile( + ":/linkify-html.js")) + messageWebView.runJavaScript(ClientWrapper.utilsAdaptor.qStringFromFile( + ":/linkify-string.js")) + messageWebView.runJavaScript(ClientWrapper.utilsAdaptor.qStringFromFile( + ":/qwebchannel.js")) + messageWebView.runJavaScript(ClientWrapper.utilsAdaptor.qStringFromFile( + ":/chatview.js")) + messageWebView.runJavaScript("init_i18n();") + messageWebView.runJavaScript("displayNavbar(false);") + } + } + Component.onCompleted: { + messageWebView.loadHtml(ClientWrapper.utilsAdaptor.qStringFromFile( + ":/chatview.html"), ":/chatview.html") + messageWebView.url = "qrc:/chatview.html" + } + } + + + /* + * Provide WebEngineProfile. + */ + WebEngineProfile { + id: messageWebViewProfile + + cachePath: ClientWrapper.utilsAdaptor.getCachePath() + persistentStoragePath: ClientWrapper.utilsAdaptor.getCachePath() + persistentCookiesPolicy: WebEngineProfile.NoPersistentCookies + httpCacheType: WebEngineProfile.NoCache + httpUserAgent: "jami-windows" + } + + + /* + * Provide WebChannel by registering jsBridgeObject. + */ + WebChannel { + id: messageWebViewChannel + registeredObjects: [jsBridgeObject] + } +} diff --git a/src/mainview/components/MessageWebViewHeader.qml b/src/mainview/components/MessageWebViewHeader.qml new file mode 100644 index 00000000..596c672a --- /dev/null +++ b/src/mainview/components/MessageWebViewHeader.qml @@ -0,0 +1,237 @@ + +/* + * Copyright (C) 2020 by Savoir-faire Linux + * Author: Mingrui Zhang + * + * 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 . + */ +import QtQuick 2.14 +import QtQuick.Controls 2.14 +import QtQuick.Layouts 1.14 +import net.jami.Models 1.0 + +import "../../commoncomponents" + +Rectangle { + id: messagingHeaderRect + + property int buttonPreferredSize: 30 + property string userAliasLabelText: "" + property string userUserNameLabelText: "" + property string backToWelcomeViewButtonSource: "qrc:/images/icons/ic_arrow_back_24px.svg" + property bool sendContactRequestButtonVisible: true + + signal backToWelcomeViewButtonClicked + signal needToHideConversationInCall + signal sendContactRequestButtonClicked + + function resetBackToWelcomeViewButtonSource(reset) { + backToWelcomeViewButtonSource = reset ? "qrc:/images/icons/ic_arrow_back_24px.svg" : "qrc:/images/icons/round-close-24px.svg" + } + + function toggleMessagingHeaderButtonsVisible(visible) { + startAAudioCallButton.visible = visible + startAVideoCallButton.visible = visible + } + + RowLayout { + id: messagingHeaderRectRowLayout + + anchors.fill: parent + + HoverableButton { + id: backToWelcomeViewButton + + Layout.alignment: Qt.AlignVCenter | Qt.AlignLeft + Layout.leftMargin: 10 + Layout.preferredWidth: buttonPreferredSize + Layout.preferredHeight: buttonPreferredSize + + radius: 30 + source: backToWelcomeViewButtonSource + backgroundColor: "white" + onExitColor: "white" + + onClicked: { + if (backToWelcomeViewButtonSource === "qrc:/images/icons/ic_arrow_back_24px.svg") + messagingHeaderRect.backToWelcomeViewButtonClicked() + else + messagingHeaderRect.needToHideConversationInCall() + } + } + + Rectangle { + id: userNameOrIdRect + + Layout.alignment: Qt.AlignVCenter | Qt.AlignLeft + + + /* + * Width + margin. + */ + Layout.preferredWidth: messagingHeaderRect.width + - backToWelcomeViewButton.width - buttonGroup.width - 45 + Layout.preferredHeight: messagingHeaderRect.height + Layout.leftMargin: 10 + + color: "transparent" + + ColumnLayout { + id: userNameOrIdColumnLayout + + Label { + id: userAliasLabel + + Layout.alignment: Qt.AlignVCenter + Layout.preferredWidth: userNameOrIdRect.width + Layout.preferredHeight: textMetricsuserAliasLabel.boundingRect.height + Layout.topMargin: userNameOrIdRect.height / 2 - userAliasLabel.height - 4 + + font.pointSize: JamiTheme.textFontSize - 1 + + horizontalAlignment: Text.AlignLeft + verticalAlignment: Text.AlignVCenter + + text: textMetricsuserAliasLabel.elidedText + } + + TextMetrics { + id: textMetricsuserAliasLabel + + font: userAliasLabel.font + text: userAliasLabelText + elideWidth: userNameOrIdRect.width + elide: Qt.ElideMiddle + } + + Label { + id: userUserNameLabel + + Layout.alignment: Qt.AlignVCenter + Layout.preferredWidth: userNameOrIdRect.width + Layout.preferredHeight: textMetricsuserUserNameLabel.boundingRect.height + + font.pointSize: JamiTheme.textFontSize - 2 + color: JamiTheme.faddedFontColor + + horizontalAlignment: Text.AlignLeft + verticalAlignment: Text.AlignVCenter + + text: textMetricsuserUserNameLabel.elidedText + } + + TextMetrics { + id: textMetricsuserUserNameLabel + + font: userUserNameLabel.font + text: userUserNameLabelText + elideWidth: userNameOrIdRect.width + elide: Qt.ElideMiddle + } + } + } + + Rectangle { + id: buttonGroup + + Layout.alignment: Qt.AlignRight | Qt.AlignVCenter + Layout.preferredWidth: buttonPreferredSize * 3 + 18 + Layout.preferredHeight: buttonPreferredSize + Layout.rightMargin: 20 + + color: "transparent" + + HoverableButton { + id: startAAudioCallButton + + anchors.right: startAVideoCallButton.left + anchors.verticalCenter: buttonGroup.verticalCenter + + height: buttonPreferredSize + width: buttonPreferredSize + + radius: 30 + source: "qrc:/images/icons/ic_phone_24px.svg" + backgroundColor: "white" + onExitColor: "white" + + onClicked: { + messagingHeaderRect.sendContactRequestButtonClicked() + CallAdapter.placeAudioOnlyCall() + } + } + + HoverableButton { + id: startAVideoCallButton + + anchors.right: sendContactRequestButton.left + anchors.leftMargin: 5 + anchors.verticalCenter: buttonGroup.verticalCenter + + height: buttonPreferredSize + width: buttonPreferredSize + + radius: 30 + source: "qrc:/images/icons/ic_video_call_24px.svg" + backgroundColor: "white" + onExitColor: "white" + + onClicked: { + messagingHeaderRect.sendContactRequestButtonClicked() + CallAdapter.placeCall() + } + } + + HoverableButton { + id: sendContactRequestButton + + anchors.leftMargin: 5 + anchors.right: buttonGroup.right + anchors.rightMargin: 8 + anchors.verticalCenter: buttonGroup.verticalCenter + + height: buttonPreferredSize + width: buttonPreferredSize + + visible: sendContactRequestButtonVisible + radius: 30 + source: "qrc:/images/icons/ic_person_add_black_24dp_2x.png" + backgroundColor: "white" + onExitColor: "white" + + onClicked: { + messagingHeaderRect.sendContactRequestButtonClicked() + sendContactRequestButtonVisible = false + } + + onVisibleChanged: { + if (sendContactRequestButton.visible) { + sendContactRequestButton.width = buttonPreferredSize + } else { + sendContactRequestButton.width = 0 + } + } + } + } + } + + CustomBorder { + commonBorder: false + lBorderwidth: 0 + rBorderwidth: 0 + tBorderwidth: 0 + bBorderwidth: 1 + borderColor: JamiTheme.tabbarBorderColor + } +} diff --git a/src/mainview/components/OutgoingCallPage.qml b/src/mainview/components/OutgoingCallPage.qml new file mode 100644 index 00000000..6148d46e --- /dev/null +++ b/src/mainview/components/OutgoingCallPage.qml @@ -0,0 +1,229 @@ + +/* + * Copyright (C) 2020 by Savoir-faire Linux + * Author: Mingrui Zhang + * + * 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 . + */ +import QtQuick 2.14 +import QtQuick.Controls 2.14 +import QtQuick.Layouts 1.14 +import QtQuick.Controls.Universal 2.12 +import net.jami.Models 1.0 + +import "../../commoncomponents" + +Rectangle { + id: outgoingCallPageRect + + property int buttonPreferredSize: 50 + property string callStatusPresentation: "outgoing" + property string contactImgSource: "" + property string bestName: "Best Name" + property string bestId: "Best Id" + + signal callCancelButtonIsClicked + signal backButtonIsClicked + + function updateUI(accountId, convUid) { + contactImgSource = "data:image/png;base64," + ClientWrapper.utilsAdaptor.getContactImageString( + accountId, convUid) + bestName = ClientWrapper.utilsAdaptor.getBestName(accountId, convUid) + var id = ClientWrapper.utilsAdaptor.getBestId(accountId, convUid) + bestId = (bestName !== id) ? id : "" + } + + anchors.fill: parent + + color: "black" + + + /* + * Prevent right click propagate to VideoCallPage. + */ + MouseArea { + anchors.fill: parent + propagateComposedEvents: false + acceptedButtons: Qt.RightButton + } + + TintedButton { + id: backTintedButton + + anchors.top: outgoingCallPageRect.top + anchors.topMargin: 10 + anchors.left: outgoingCallPageRect.left + anchors.leftMargin: 5 + + width: 30 + height: 30 + + tintColor: JamiTheme.buttonTintedBlue + normalPixmapSource: "qrc:/images/icons/ic_arrow_back_white_24dp.png" + selectedPixmapSource: "qrc:/images/icons/ic_arrow_back_white_24dp.png" + + onClicked: { + outgoingCallPageRect.backButtonIsClicked() + } + } + + ColumnLayout { + id: outgoingCallPageRectColumnLayout + + anchors.fill: parent + + Image { + id: contactImg + + Layout.alignment: Qt.AlignCenter + + Layout.preferredWidth: 100 + Layout.preferredHeight: 100 + + fillMode: Image.PreserveAspectFit + source: contactImgSource + asynchronous: true + } + + Rectangle { + id: outgoingCallPageTextRect + + Layout.alignment: Qt.AlignCenter + Layout.topMargin: 5 + + Layout.preferredWidth: outgoingCallPageRect.width + Layout.preferredHeight: jamiBestNameText.height + jamiBestIdText.height + + callStatusText.height + spinnerImage.height + 20 + + color: "transparent" + + ColumnLayout { + id: outgoingCallPageTextRectColumnLayout + + Text { + id: jamiBestNameText + + Layout.alignment: Qt.AlignCenter + Layout.preferredWidth: outgoingCallPageTextRect.width + Layout.preferredHeight: 50 + + font.pointSize: JamiTheme.textFontSize + 3 + + horizontalAlignment: Text.AlignHCenter + verticalAlignment: Text.AlignVCenter + + text: textMetricsjamiBestNameText.elidedText + color: "white" + + TextMetrics { + id: textMetricsjamiBestNameText + font: jamiBestNameText.font + text: bestName + elideWidth: outgoingCallPageTextRect.width - 50 + elide: Qt.ElideMiddle + } + } + + Text { + id: jamiBestIdText + + Layout.alignment: Qt.AlignCenter + Layout.preferredWidth: outgoingCallPageTextRect.width + Layout.preferredHeight: 30 + + font.pointSize: JamiTheme.textFontSize + + horizontalAlignment: Text.AlignHCenter + verticalAlignment: Text.AlignVCenter + + text: textMetricsjamiBestIdText.elidedText + color: Qt.lighter("white", 1.5) + + TextMetrics { + id: textMetricsjamiBestIdText + font: jamiBestIdText.font + text: bestId + elideWidth: outgoingCallPageTextRect.width - 50 + elide: Qt.ElideMiddle + } + } + + AnimatedImage { + id: spinnerImage + + Layout.alignment: Qt.AlignCenter + Layout.preferredWidth: 20 + Layout.preferredHeight: 5 + + source: "qrc:/images/waiting.gif" + } + + Text { + id: callStatusText + + Layout.alignment: Qt.AlignCenter + Layout.preferredWidth: outgoingCallPageTextRect.width + Layout.preferredHeight: 30 + + font.pointSize: JamiTheme.textFontSize + + horizontalAlignment: Text.AlignHCenter + verticalAlignment: Text.AlignVCenter + + text: callStatusPresentation + "..." + color: Qt.lighter("white", 1.5) + } + } + } + + ColumnLayout { + id: callCancelButtonColumnLayout + + Layout.alignment: Qt.AlignCenter + + HoverableButton { + id: callCancelButton + + Layout.alignment: Qt.AlignCenter + + Layout.preferredWidth: buttonPreferredSize + Layout.preferredHeight: buttonPreferredSize + + backgroundColor: JamiTheme.declineButtonRed + onEnterColor: JamiTheme.declineButtonHoverRed + onPressColor: JamiTheme.declineButtonPressedRed + onReleaseColor: JamiTheme.declineButtonHoverRed + onExitColor: JamiTheme.declineButtonRed + + buttonImageHeight: buttonPreferredSize / 2 + buttonImageWidth: buttonPreferredSize / 2 + source: "qrc:/images/icons/ic_close_white_24dp.png" + radius: 30 + + onClicked: { + outgoingCallPageRect.callCancelButtonIsClicked() + } + } + + Text { + id: cancelText + + Layout.alignment: Qt.AlignCenter + + font.pointSize: JamiTheme.textFontSize - 2 + text: qsTr("Cancel") + } + } + } +} diff --git a/src/mainview/components/ProjectCreditsScrollView.qml b/src/mainview/components/ProjectCreditsScrollView.qml new file mode 100644 index 00000000..0606f04c --- /dev/null +++ b/src/mainview/components/ProjectCreditsScrollView.qml @@ -0,0 +1,61 @@ + +/* + * Copyright (C) 2020 by Savoir-faire Linux + * Author: Mingrui Zhang + * + * 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 . + */ +import QtQuick 2.14 +import QtQuick.Controls 2.14 +import net.jami.Models 1.0 + +ScrollView { + id: projectCreditsScrollView + + anchors.fill: parent + + clip: true + + ScrollBar.horizontal.policy: ScrollBar.AlwaysOff + + TextEdit { + id: projectCreditsTextArea + + horizontalAlignment: Text.AlignHCenter + + width: projectCreditsScrollView.width + + selectByMouse: false + readOnly: true + wrapMode: Text.WordWrap + + font.pointSize: JamiTheme.textFontSize - 3 + text: ClientWrapper.utilsAdaptor.getProjectCredits() + textFormat: TextEdit.RichText + + MouseArea { + anchors.fill: parent + propagateComposedEvents: true + cursorShape: Qt.ArrowCursor + acceptedButtons: Qt.NoButton + } + } + + background: Rectangle { + id: projectCreditsScrollViewBackground + + radius: 5 + border.color: JamiTheme.tabbarBorderColor + } +} diff --git a/src/mainview/components/RecordBox.qml b/src/mainview/components/RecordBox.qml new file mode 100644 index 00000000..b6bc0f99 --- /dev/null +++ b/src/mainview/components/RecordBox.qml @@ -0,0 +1,318 @@ +/* + * Copyright (C) 2020 by Savoir-faire Linux + * Author: Albert Babí + * + * 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 . + */ + +import QtQuick 2.15 +import QtQuick.Controls 2.14 +import QtQuick.Layouts 1.14 +import QtQuick.Controls.Styles 1.4 +import QtQuick.Dialogs 1.3 +import QtGraphicalEffects 1.0 +import net.jami.Models 1.0 +import "../../commoncomponents" + + +Rectangle { + + enum States { + INIT, + RECORDING, + REC_SUCCESS + } + + id:recBox + color: "#FFFFFF" + width: 320 + height: 240 + radius: 5 + border.color: JamiTheme.tabbarBorderColor + + property string pathRecorder: "" + property string timeText: "00:00" + property int duration: 0 + property int state: RecordBox.States.INIT + property bool isVideo: false + property bool previewAvailable: false + + property int h_offset: -65 + property int v_offset: -65 + + function openRecorder(set_x, set_y, vid) { + focus = true + visible = true + x = set_x+(width/2)+h_offset + y = set_y-(height/2)+v_offset + + updateState(RecordBox.States.INIT) + + isVideo = vid + if (isVideo){ + ClientWrapper.accountAdaptor.startPreviewing(false) + previewAvailable = true + } + } + + onActiveFocusChanged: { + if (visible) { + closeRecorder() + } + } + + onVisibleChanged: { + if(!visible) { + closeRecorder() + } + } + + function closeRecorder() { + if (isVideo && ClientWrapper.accountAdaptor.isPreviewing()) { + ClientWrapper.accountAdaptor.stopPreviewing() + } + stopRecording() + visible = false + } + + function updateState(new_state) { + state = new_state + recordButton.visible = (state == RecordBox.States.INIT) + btnStop.visible = (state == RecordBox.States.RECORDING) + btnRestart.visible = (state == RecordBox.States.REC_SUCCESS) + btnSend.visible = (state == RecordBox.States.REC_SUCCESS) + + if (state == RecordBox.States.INIT) { + duration = 0 + time.text = "00:00" + timer.stop() + } else if (state == RecordBox.States.REC_SUCCESS) { + timer.stop() + } + } + + function startRecording() { + timer.start() + pathRecorder = ClientWrapper.avmodel.startLocalRecorder(!isVideo) + if (pathRecorder == "") { + timer.stop() + } + } + + function stopRecording() { + if (pathRecorder != "") { + ClientWrapper.avmodel.stopLocalRecorder(pathRecorder) + } + } + + function sendRecord() { + if (pathRecorder != "") { + MessagesAdapter.sendFile(pathRecorder) + } + } + + function updateTimer() { + + duration += 1 + + var m = Math.trunc(duration / 60) + var s = (duration % 60) + + var min = (m < 10) ? "0" + String(m) : String(m) + var sec = (s < 10) ? "0" + String(s) : String(s) + + time.text = min + ":" + sec; + } + + + Connections{ + target: ClientWrapper.renderManager + } + + Rectangle { + id: rectBox + visible: (isVideo && previewAvailable) + Layout.alignment: Qt.AlignHCenter + anchors.fill: parent + color: "black" + radius: 5 + + PreviewRenderer{ + id: previewWidget + anchors.fill: rectBox + anchors.centerIn: rectBox + layer.enabled: true + layer.effect: OpacityMask { + maskSource: rectBox + } + } + } + + Label { + visible: (isVideo && !previewAvailable) + + Layout.fillWidth: true + Layout.alignment: Qt.AlignCenter + + text: qsTr("Preview unavailable") + font.pointSize: 10 + font.kerning: true + } + + Timer { + id: timer + interval: 1000; + running: false; + repeat: true + onTriggered: updateTimer() + } + + Text { + id: time + visible: true + text: "00:00" + color: (isVideo ? "white" : "black") + font.pointSize: (isVideo ? 12 : 20) + anchors.horizontalCenter: parent.horizontalCenter + anchors.horizontalCenterOffset: (isVideo ? 100 : 0) + anchors.verticalCenter: parent.verticalCenter + anchors.verticalCenterOffset: (isVideo ? 100 : 0) + } + + + HoverableRadiusButton { + id: recordButton + Layout.maximumWidth: 30 + Layout.preferredWidth: 30 + Layout.minimumWidth: 30 + + Layout.maximumHeight: 30 + Layout.preferredHeight: 30 + Layout.minimumHeight: 30 + + buttonImageHeight: height + buttonImageWidth: height + backgroundColor: isVideo? "#000000cc" : "white" + + anchors.horizontalCenter: parent.horizontalCenter + anchors.bottom: parent.bottom + anchors.bottomMargin: 5 + + radius: height / 2 + + icon.source: "qrc:/images/icons/av_icons/fiber_manual_record-24px.svg" + icon.height: 24 + icon.width: 24 + icon.color: "#dc2719" + onClicked: { + updateState(RecordBox.States.RECORDING) + startRecording() + } + } + + HoverableRadiusButton { + id: btnStop + Layout.maximumWidth: 30 + Layout.preferredWidth: 30 + Layout.minimumWidth: 30 + + Layout.maximumHeight: 30 + Layout.preferredHeight: 30 + Layout.minimumHeight: 30 + + buttonImageHeight: height + buttonImageWidth: height + backgroundColor: isVideo? "#000000cc" : "white" + + anchors.horizontalCenter: parent.horizontalCenter + anchors.bottom: parent.bottom + anchors.bottomMargin: 5 + + radius: height / 2 + + icon.source: "qrc:/images/icons/av_icons/stop-24px-red.svg" + icon.height: 24 + icon.width: 24 + icon.color: isVideo? "white" : "black" + onClicked: { + stopRecording() + updateState(RecordBox.States.REC_SUCCESS) + } + } + + HoverableRadiusButton { + id: btnRestart + Layout.maximumWidth: 30 + Layout.preferredWidth: 30 + Layout.minimumWidth: 30 + + Layout.maximumHeight: 30 + Layout.preferredHeight: 30 + Layout.minimumHeight: 30 + + buttonImageHeight: height + buttonImageWidth: height + backgroundColor: isVideo? "#000000cc" : "white" + + anchors.horizontalCenter: parent.horizontalCenter + anchors.right: btnRestart.left + anchors.rightMargin: 5 + anchors.bottom: parent.bottom + anchors.bottomMargin: 5 + + radius: height / 2 + + icon.source: "qrc:/images/icons/av_icons/re-record-24px.svg" + icon.height: 24 + icon.width: 24 + icon.color: isVideo? "white" : "black" + onClicked: { + stopRecording() + updateState(RecordBox.States.INIT) + } + } + + HoverableRadiusButton { + id: btnSend + Layout.maximumWidth: 30 + Layout.preferredWidth: 30 + Layout.minimumWidth: 30 + + Layout.maximumHeight: 30 + Layout.preferredHeight: 30 + Layout.minimumHeight: 30 + + buttonImageHeight: height + buttonImageWidth: height + backgroundColor: isVideo? "#000000cc" : "white" + + anchors.left: btnRestart.right + anchors.leftMargin: 5 + anchors.bottom: parent.bottom + anchors.bottomMargin: 5 + + radius: height / 2 + + icon.source: "qrc:/images/icons/av_icons/send-24px.svg" + icon.height: 24 + icon.width: 24 + icon.color: isVideo? "white" : "black" + onClicked: { + stopRecording() + sendRecord() + closeRecorder() + updateState(RecordBox.States.INIT) + } + } +} diff --git a/src/mainview/components/ScreenRubberBand.qml b/src/mainview/components/ScreenRubberBand.qml new file mode 100644 index 00000000..65c3266e --- /dev/null +++ b/src/mainview/components/ScreenRubberBand.qml @@ -0,0 +1,113 @@ + +/* + * Copyright (C) 2020 by Savoir-faire Linux + * Author: Mingrui Zhang + * + * 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 . + */ +import QtQuick 2.14 +import QtQuick.Window 2.14 +import QtQuick.Controls 2.14 +import QtQuick.Layouts 1.14 +import QtQuick.Controls.Universal 2.12 +import net.jami.Models 1.0 + + +/* + * ScreenRubberBand as a seperate frameless window, + * is to simulate the whole screen area and provide the user + * the ability to select certain area of it. + * + * Typically, it is used for video screen sharing. + */ +Window { + id: screenRubberBandWindow + + property int screenNumber: 0 + + flags: Qt.FramelessWindowHint | Qt.WindowStaysOnTopHint | Qt.WA_TranslucentBackground + + + /* + * Opacity with 0.7 window that will fill the entire screen, + * provide the users to select the area that they + * want to share. + */ + color: Qt.rgba(0, 0, 0, 0.7) + + + /* + * Rect for selection. + */ + Rectangle { + id: recSelect + + height: 0 + width: 0 + + border.color: JamiTheme.rubberBandSelectionBlue + border.width: 1 + color: JamiTheme.rubberBandSelectionBlue + opacity: 0.3 + visible: false + } + + MouseArea { + id: screenRubberBandMouseArea + + property int originalX: 0 + property int originalY: 0 + + anchors.fill: parent + hoverEnabled: true + cursorShape: Qt.CrossCursor + + + /* + * Geo changing for user selection. + */ + onPressed: { + originalX = mouseX + originalY = mouseY + recSelect.x = mouseX + recSelect.y = mouseY + recSelect.visible = true + } + + onMouseXChanged: { + if (originalX - mouseX >= 0) { + recSelect.x = mouseX + recSelect.width = originalX - recSelect.x + } else if (mouseX - recSelect.x > 0) { + recSelect.width = mouseX - recSelect.x + } + } + + onMouseYChanged: { + if (originalY - mouseY >= 0) { + recSelect.y = mouseY + recSelect.height = originalY - recSelect.y + } else if (mouseY - recSelect.y > 0) { + recSelect.height = mouseY - recSelect.y + } + } + + onReleased: { + recSelect.visible = false + AvAdapter.shareScreenArea(screenNumber, recSelect.x, recSelect.y, + recSelect.width, recSelect.height) + screenRubberBandWindow.close() + } + } +} diff --git a/src/mainview/components/SelectScreen.qml b/src/mainview/components/SelectScreen.qml new file mode 100644 index 00000000..506af487 --- /dev/null +++ b/src/mainview/components/SelectScreen.qml @@ -0,0 +1,320 @@ + +/* + * Copyright (C) 2020 by Savoir-faire Linux + * Author: Mingrui Zhang + * + * 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 . + */ +import QtQuick 2.14 +import QtQuick.Window 2.14 +import QtQuick.Controls 2.14 +import QtQuick.Layouts 1.14 +import QtQuick.Controls.Universal 2.12 +import net.jami.Models 1.0 + +import "../js/screenrubberbandcreation.js" as ScreenRubberBandCreation + +import "../../commoncomponents" + + +/* + * SelectScreenWindow as a seperate window, + * is to make user aware of which screen they want to share, + * during the video call, if the context menu item is selected. + */ +Window { + id: selectScreenWindow + + property int minWidth: 650 + property int minHeight: 500 + + property int selectedScreenNumber: -1 + + + /* + * Decide whether to show screen area or entire screen. + */ + property bool selectArea: false + + + /* + * How many rows the ScrollView should have. + */ + function calculateRepeaterModel() { + var numberOfScreens = Qt.application.screens.length + + if (numberOfScreens % 2 === 1) + return numberOfScreens / 2 + 1 + else + return numberOfScreens / 2 + } + + function calculateScreenNumber(index) { + if (index === 0 || index === 1) + return index + if (index % 2 === 0) + return index * 2 + else + return index * 2 + 1 + } + + minimumWidth: minWidth + minimumHeight: minHeight + + title: "Screen sharing" + + + /* + * Note: Qt.application.screens[0] is the app's current existing screen. + */ + screen: Qt.application.screens[0] + + Rectangle { + id: selectScreenWindowRect + + anchors.fill: parent + + Text { + id: screenListText + + anchors.top: selectScreenWindowRect.top + anchors.topMargin: 20 + anchors.horizontalCenter: selectScreenWindowRect.horizontalCenter + + font.pointSize: JamiTheme.textFontSize + 2 + font.bold: true + text: qsTr("Choose A Screen to Share") + } + + ScrollView { + id: screenSelectionScrollView + + anchors.centerIn: selectScreenWindowRect + + width: selectScreenWindowRect.width - 50 + height: selectScreenWindowRect.height - 150 + + clip: true + + ScrollBar.horizontal.policy: ScrollBar.AlwaysOff + + + /* + * Column of rows repeater (two screen captures in a row). + */ + Column { + id: screenSelectionScrollViewColumn + + spacing: 10 + + Repeater { + id: screenInfo + + model: calculateRepeaterModel() + + Row { + id: screenInfoRow + + spacing: 20 + + Connections { + target: selectScreenWindow + + function onSelectedScreenNumberChanged() { + + + /* + * Recover from green state. + */ + screenSelectionRectOdd.borderColor = JamiTheme.tabbarBorderColor + screenSelectionRectEven.borderColor = JamiTheme.tabbarBorderColor + } + } + + + /* + * To make sure that two screen captures in one row, + * a repeater of two rect is needed, which one in charge + * of odd number screen, one in charge of even number screen. + */ + Rectangle { + id: screenSelectionRectOdd + + property string borderColor: JamiTheme.tabbarBorderColor + + height: screenSelectionScrollView.height + width: screenSelectionScrollView.width / 2 - screenInfoRow.spacing / 2 + + radius: 10 + border.color: borderColor + + Image { + id: screenShotOdd + + anchors.top: screenSelectionRectOdd.top + anchors.topMargin: 10 + anchors.horizontalCenter: screenSelectionRectOdd.horizontalCenter + + height: screenSelectionRectOdd.height - 50 + width: screenSelectionRectOdd.width - 50 + + fillMode: Image.PreserveAspectFit + mipmap: true + + Component.onCompleted: { + screenShotOdd.source = "data:image/png;base64," + + AvAdapter.captureScreen( + calculateScreenNumber(index)) + } + } + + Text { + id: screenNameOdd + + anchors.top: screenShotOdd.bottom + anchors.topMargin: 10 + anchors.horizontalCenter: screenSelectionRectOdd.horizontalCenter + + font.pointSize: JamiTheme.textFontSize - 2 + text: qsTr("Screen") + " " + (calculateScreenNumber( + index) + 1) + } + + MouseArea { + anchors.fill: parent + acceptedButtons: Qt.LeftButton + + onClicked: { + if (selectedScreenNumber == -1 + || selectedScreenNumber !== calculateScreenNumber( + index)) { + selectedScreenNumber = calculateScreenNumber( + index) + screenSelectionRectOdd.borderColor + = JamiTheme.screenSelectionBorderGreen + } + } + } + } + + Rectangle { + id: screenSelectionRectEven + + property string borderColor: JamiTheme.tabbarBorderColor + + height: screenSelectionScrollView.height + width: screenSelectionScrollView.width / 2 - screenInfoRow.spacing / 2 + + radius: 10 + border.color: borderColor + + visible: (Qt.application.screens.length) % 2 != 1 + + Image { + id: screenShotEven + + anchors.top: screenSelectionRectEven.top + anchors.topMargin: 10 + anchors.horizontalCenter: screenSelectionRectEven.horizontalCenter + + height: screenSelectionRectEven.height - 50 + width: screenSelectionRectEven.width - 50 + + fillMode: Image.PreserveAspectFit + mipmap: true + + Component.onCompleted: { + if (screenSelectionRectEven.visible) + screenShotEven.source = "data:image/png;base64," + + AvAdapter.captureScreen( + calculateScreenNumber( + index + 1)) + } + } + + Text { + id: screenNameEven + + anchors.top: screenShotEven.bottom + anchors.topMargin: 10 + anchors.horizontalCenter: screenSelectionRectEven.horizontalCenter + + font.pointSize: JamiTheme.textFontSize - 2 + text: qsTr( + "Screen") + " " + (calculateScreenNumber( + index + 1) + 1) + } + + MouseArea { + anchors.fill: parent + acceptedButtons: Qt.LeftButton + + onClicked: { + if (selectedScreenNumber == -1 + || selectedScreenNumber !== calculateScreenNumber( + index + 1)) { + selectedScreenNumber = calculateScreenNumber( + index + 1) + screenSelectionRectEven.borderColor + = JamiTheme.screenSelectionBorderGreen + } + } + } + } + } + } + } + + background: Rectangle { + id: screenSelectionScrollViewBackground + + radius: 10 + border.color: JamiTheme.tabbarBorderColor + } + } + } + + HoverableButton { + id: selectButton + + anchors.bottom: selectScreenWindowRect.bottom + anchors.bottomMargin: 10 + anchors.horizontalCenter: selectScreenWindowRect.horizontalCenter + + visible: selectedScreenNumber != -1 + + text: qsTr("Share Screen") + radius: 10 + + onClicked: { + if (selectArea) { + selectScreenWindow.hide() + ScreenRubberBandCreation.createScreenRubberBandWindowObject( + selectScreenWindow, selectedScreenNumber) + ScreenRubberBandCreation.showScreenRubberBandWindow() + + + /* + * Destory selectScreenWindow once screenRubberBand is closed. + */ + ScreenRubberBandCreation.connectOnClosingEvent(function () { + selectScreenWindow.close() + }) + } else { + AvAdapter.shareEntireScreen(selectedScreenNumber) + selectScreenWindow.close() + } + } + } +} diff --git a/src/mainview/components/SidePanel.qml b/src/mainview/components/SidePanel.qml new file mode 100644 index 00000000..1a81d1ca --- /dev/null +++ b/src/mainview/components/SidePanel.qml @@ -0,0 +1,311 @@ + +/* + * Copyright (C) 2020 by Savoir-faire Linux + * Author: Mingrui Zhang + * + * 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 . + */ +import QtQuick 2.14 +import QtQuick.Controls 2.14 +import QtQuick.Layouts 1.14 +import net.jami.Models 1.0 + +import "../../commoncomponents" + +Rectangle { + id: sidePanelRect + + property bool tabBarVisible: true + property int pendingRequestCount: 0 + property int totalUnreadMessagesCount: 0 + + signal conversationSmartListNeedToAccessMessageWebView(string currentUserDisplayName, string currentUserAlias, string currentUID, bool callStackViewShouldShow, bool isAudioOnly, string callStateStr) + signal accountComboBoxNeedToShowWelcomePage(int index) + signal conversationSmartListViewNeedToShowWelcomePage + signal accountSignalsReconnect(string accountId) + signal needToUpdateConversationForAddedContact + signal needToAddNewAccount + signal settingBtnClicked_AccountComboBox + + + /* + * Hack -> force redraw. + */ + function forceReselectConversationSmartListCurrentIndex() { + var index = conversationSmartListView.currentIndex + conversationSmartListView.currentIndex = -1 + conversationSmartListView.currentIndex = index + } + + + /* + * For contact request conv to be focused correctly. + */ + function setCurrentUidSmartListModelIndex() { + conversationSmartListView.currentIndex + = conversationSmartListView.model.currentUidSmartListModelIndex( + ) + } + + function updatePendingRequestCount() { + pendingRequestCount = ClientWrapper.utilsAdaptor.getTotalPendingRequest() + } + + function updateTotalUnreadMessagesCount() { + totalUnreadMessagesCount = ClientWrapper.utilsAdaptor.getTotalUnreadMessages() + } + + function clearContactSearchBar() { + contactSearchBar.clearText() + } + + function accountChangedUIReset() { + contactSearchBar.clearText() + contactSearchBar.setPlaceholderString( + JamiTheme.contactSearchBarPlaceHolderConversationText) + sidePanelTabBar.converstationTabDown = true + sidePanelTabBar.invitationTabDown = false + } + + function needToChangeToAccount(accountId, index) { + if (index !== -1) { + accountComboBox.currentIndex = index + ClientWrapper.accountAdaptor.accountChanged(index) + accountChangedUIReset() + } + } + + function refreshAccountComboBox(index = -1) { + accountComboBox.resetAccountListModel() + + + /* + * To make sure that the ui is refreshed for accountComboBox. + * Note: when index in -1, it means to maintain the + * current account selection. + */ + var currentIndex = accountComboBox.currentIndex + if (accountComboBox.currentIndex === index) + accountComboBox.currentIndex = -1 + accountComboBox.currentIndex = index + if (index !== -1) + ClientWrapper.accountAdaptor.accountChanged(index) + else + accountComboBox.currentIndex = currentIndex + accountComboBox.update() + accountChangedUIReset() + } + + function deselectConversationSmartList() { + ConversationsAdapter.deselectConversation() + conversationSmartListView.currentIndex = -1 + } + + function forceUpdateConversationSmartListView() { + conversationSmartListView.updateConversationSmartListView() + } + + + /* + * Intended -> since strange behavior will happen without this for stackview. + */ + anchors.fill: parent + + AccountComboBox { + id: accountComboBox + + anchors.top: sidePanelRect.top + + width: sidePanelRect.width + height: 60 + + currentIndex: 0 + + Connections { + target: ClientWrapper.accountAdaptor + + function onAccountSignalsReconnect(accountId) { + CallAdapter.connectCallStatusChanged(accountId) + ConversationsAdapter.accountChangedSetUp(accountId) + sidePanelRect.accountSignalsReconnect(accountId) + } + + function onUpdateConversationForAddedContact() { + sidePanelRect.needToUpdateConversationForAddedContact() + } + + function onAccountStatusChanged() { + accountComboBox.updateAccountListModel() + } + } + + onSettingBtnClicked: { + settingBtnClicked_AccountComboBox() + } + + onAccountChanged: { + ClientWrapper.accountAdaptor.accountChanged(index) + accountChangedUIReset() + } + + onNeedToUpdateSmartList: { + conversationSmartListView.currentIndex = -1 + conversationSmartListView.updateSmartList(accountId) + } + + onNeedToBackToWelcomePage: { + sidePanelRect.accountComboBoxNeedToShowWelcomePage(index) + } + + onNewAccountButtonClicked: { + sidePanelRect.needToAddNewAccount() + } + + Component.onCompleted: { + ClientWrapper.accountAdaptor.setQmlObject(this) + ClientWrapper.accountAdaptor.accountChanged(0) + } + } + + SidePanelTabBar { + id: sidePanelTabBar + + anchors.top: accountComboBox.bottom + anchors.topMargin: 20 + anchors.left: sidePanelRect.left + anchors.leftMargin: tabBarLeftMargin + + width: sidePanelRect.width + height: Math.max(sidePanelTabBar.converstationTabHeight, + sidePanelTabBar.invitationTabHeight) + } + + Rectangle { + id: sidePanelColumnRect + + anchors.top: sidePanelTabBar.bottom + anchors.topMargin: -12 + + width: sidePanelRect.width + height: sidePanelRect.height - accountComboBox.height - sidePanelTabBar.height + + border.color: JamiTheme.tabbarBorderColor + radius: 10 + + Rectangle { + id: hideTopBoarderRect + + anchors.top: sidePanelColumnRect.top + anchors.left: sidePanelColumnRect.left + anchors.leftMargin: tabBarLeftMargin + 5 + + width: sidePanelTabBar.converstationTabWidth + sidePanelTabBar.invitationTabWidth - 9 + height: 1 + + visible: tabBarVisible + + color: "white" + } + + ColumnLayout { + id: columnLayoutView + + anchors.centerIn: sidePanelColumnRect + + width: sidePanelColumnRect.width + height: sidePanelColumnRect.height - 20 + + + /* + * Search bar container to embed search label + */ + ContactSearchBar { + id: contactSearchBar + + Layout.alignment: Qt.AlignCenter + Layout.topMargin: 10 + Layout.rightMargin: 5 + Layout.leftMargin: 5 + Layout.preferredWidth: parent.width - 10 + Layout.preferredHeight: 35 + + onContactSearchBarTextChanged: { + ClientWrapper.utilsAdaptor.setConversationFilter(text) + } + } + + ConversationSmartListView { + id: conversationSmartListView + + Layout.alignment: Qt.AlignCenter + Layout.preferredWidth: parent.width + Layout.preferredHeight: parent.height - contactSearchBar.height - 30 + + Connections { + target: ConversationsAdapter + + function onShowChatView(accountId, convUid) { + conversationSmartListView.needToShowChatView(accountId, + convUid) + } + + function onShowConversationTabs(visible) { + tabBarVisible = visible + updatePendingRequestCount() + updateTotalUnreadMessagesCount() + } + } + + onNeedToSelectItems: { + ConversationsAdapter.selectConversation(index) + } + + onNeedToBackToWelcomePage: { + sidePanelRect.conversationSmartListViewNeedToShowWelcomePage() + } + + onNeedToAccessMessageWebView: { + sidePanelRect.conversationSmartListNeedToAccessMessageWebView( + currentUserDisplayName, currentUserAlias, + currentUID, callStackViewShouldShow, + isAudioOnly, callStateStr) + } + + onNeedToGrabFocus: { + contactSearchBar.clearFocus() + } + + Component.onCompleted: { + ConversationsAdapter.setQmlObject(this) + conversationSmartListView.currentIndex = -1 + } + } + } + } + + onTabBarVisibleChanged: { + if (!tabBarVisible) { + sidePanelTabBar.height = 0 + sidePanelTabBar.anchors.topMargin = 12 + sidePanelColumnRect.border.width = 0 + } else { + sidePanelTabBar.height = Qt.binding(function () { + return Math.max(sidePanelTabBar.converstationTabHeight, + sidePanelTabBar.invitationTabHeight) + }) + sidePanelTabBar.anchors.topMargin = 20 + sidePanelColumnRect.border.width = 1 + } + } +} diff --git a/src/mainview/components/SidePanelTabBar.qml b/src/mainview/components/SidePanelTabBar.qml new file mode 100644 index 00000000..d8197e1f --- /dev/null +++ b/src/mainview/components/SidePanelTabBar.qml @@ -0,0 +1,199 @@ + +/* + * Copyright (C) 2020 by Savoir-faire Linux + * Author: Mingrui Zhang + * + * 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 . + */ +import QtQuick 2.14 +import QtQuick.Controls 2.14 +import QtQuick.Layouts 1.14 +import net.jami.Models 1.0 + +TabBar { + id: tabBar + + property alias converstationTabDown: pageOne.down + property alias invitationTabDown: pageTwo.down + property alias converstationTabWidth: pageOne.width + property alias invitationTabWidth: pageTwo.width + property alias converstationTabHeight: pageOne.height + property alias invitationTabHeight: pageTwo.height + + visible: tabBarVisible + + currentIndex: 0 + + TabButton { + id: pageOne + + width: tabBar.width / 2 - tabButtonShrinkSize + height: textConvElement.height + 10 + + down: true + + Rectangle { + id: totalUnreadMessagesCountRect + + anchors.right: pageOne.right + anchors.rightMargin: 5 + anchors.bottom: pageOne.bottom + anchors.bottomMargin: pageOne.height - totalUnreadMessagesCountRect.height / 2 + + width: 14 + height: 14 + + visible: totalUnreadMessagesCount > 0 + + Text { + id: totalUnreadMessagesCountText + + anchors.centerIn: totalUnreadMessagesCountRect + + text: totalUnreadMessagesCount > 9 ? "···" : totalUnreadMessagesCount + color: "white" + } + + radius: 30 + color: JamiTheme.notificationRed + } + + background: Rectangle { + id: buttonRectOne + + radius: 10 + width: pageOne.width + 2 + color: pageOne.down ? "white" : JamiTheme.releaseColor + border.color: JamiTheme.tabbarBorderColor + + Text { + id: textConvElement + + anchors.centerIn: buttonRectOne + + horizontalAlignment: Text.AlignHCenter + verticalAlignment: Text.AlignVCenter + + text: qsTr("Converstation") + font.pointSize: JamiTheme.textFontSize + opacity: enabled ? 1.0 : 0.3 + } + + MouseArea { + anchors.fill: parent + hoverEnabled: true + onPressed: { + buttonRectOne.color = JamiTheme.pressColor + ConversationsAdapter.setConversationFilter("") + contactSearchBar.setPlaceholderString( + JamiTheme.contactSearchBarPlaceHolderConversationText) + pageOne.down = true + pageTwo.down = false + setCurrentUidSmartListModelIndex() + forceReselectConversationSmartListCurrentIndex() + } + onReleased: { + buttonRectOne.color = JamiTheme.releaseColor + } + onEntered: { + buttonRectOne.color = JamiTheme.hoverColor + } + onExited: { + buttonRectOne.color = Qt.binding(function () { + return pageOne.down ? "white" : JamiTheme.releaseColor + }) + } + } + } + } + + TabButton { + id: pageTwo + + width: tabBar.width / 2 - tabButtonShrinkSize + height: textInvElement.height + 10 + + Rectangle { + id: pendingRequestCountRect + + anchors.right: pageTwo.right + anchors.rightMargin: 5 + anchors.bottom: pageTwo.bottom + anchors.bottomMargin: pageTwo.height - pendingRequestCountRect.height / 2 + + width: 14 + height: 14 + + visible: pendingRequestCount > 0 + + Text { + id: pendingRequestCountText + + anchors.centerIn: pendingRequestCountRect + + text: pendingRequestCount > 9 ? "···" : pendingRequestCount + color: "white" + } + + radius: 30 + color: JamiTheme.notificationRed + } + + background: Rectangle { + id: buttonRectTwo + + radius: 10 + color: pageTwo.down ? "white" : JamiTheme.releaseColor + border.color: JamiTheme.tabbarBorderColor + + Text { + id: textInvElement + + anchors.centerIn: buttonRectTwo + + horizontalAlignment: Text.AlignHCenter + verticalAlignment: Text.AlignVCenter + + font.pointSize: JamiTheme.textFontSize + + text: qsTr("Invitation") + opacity: enabled ? 1.0 : 0.3 + } + + MouseArea { + anchors.fill: parent + hoverEnabled: true + onPressed: { + buttonRectTwo.color = JamiTheme.pressColor + ConversationsAdapter.setConversationFilter("PENDING") + contactSearchBar.setPlaceholderString( + JamiTheme.contactSearchBarPlaceHolderInivitionText) + pageTwo.down = true + pageOne.down = false + } + onReleased: { + buttonRectTwo.color = JamiTheme.releaseColor + } + onEntered: { + buttonRectTwo.color = JamiTheme.hoverColor + } + onExited: { + buttonRectTwo.color = Qt.binding(function () { + return pageTwo.down ? "white" : JamiTheme.releaseColor + }) + } + } + } + } +} diff --git a/src/mainview/components/UserProfile.qml b/src/mainview/components/UserProfile.qml new file mode 100644 index 00000000..072d9a6e --- /dev/null +++ b/src/mainview/components/UserProfile.qml @@ -0,0 +1,170 @@ + +/* + * Copyright (C) 2020 by Savoir-faire Linux + * Author: Mingrui Zhang + * + * 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 . + */ +import QtQuick 2.14 +import QtQuick.Controls 2.14 +import QtQuick.Layouts 1.14 +import net.jami.Models 1.0 + +import "../../commoncomponents" + +Dialog { + id: userProfileDialog + + property string responsibleConvUid: "" + property string contactPicBase64: "" + property string aliasText: "" + property string registeredNameText: "" + property string idText: "" + + modal: true + + + /* + * Content height + margin. + */ + contentHeight: userProfileDialogUpperPartColumnLayout.implicitHeight + 30 + + + /* + * Fake focus to make sure that text edit lose focus on close. + */ + FocusScope { + id: fakeFocusTextEdit + } + + ColumnLayout { + id: userProfileDialogUpperPartColumnLayout + + anchors.centerIn: parent + + spacing: 15 + + Image { + id: contactImage + + Layout.alignment: Qt.AlignCenter + + width: 150 + height: 150 + + fillMode: Image.PreserveAspectFit + mipmap: true + } + + + /* + * Visible when user alias is not empty or equals to id. + */ + Text { + id: contactAlias + + Layout.alignment: Qt.AlignCenter + + font.pointSize: JamiTheme.textFontSize + text: textMetricsContactAliasText.elidedText + visible: aliasText ? (aliasText === idText ? false : true) : false + TextMetrics { + id: textMetricsContactAliasText + font: contactAlias.font + text: aliasText + elideWidth: userProfileDialog.width - 30 + elide: Qt.ElideMiddle + } + } + + + /* + * Visible when user name is not empty or equals to alias. + */ + Text { + id: contactDisplayName + + Layout.alignment: Qt.AlignCenter + + font.pointSize: JamiTheme.textFontSize - 1 + text: textMetricsContactDisplayNameText.elidedText + visible: registeredNameText ? (registeredNameText === aliasText ? false : true) : false + color: JamiTheme.faddedFontColor + + TextMetrics { + id: textMetricsContactDisplayNameText + font: contactDisplayName.font + text: registeredNameText + elideWidth: userProfileDialog.width - 30 + elide: Qt.ElideMiddle + } + } + + TextEdit { + id: contactId + + Layout.alignment: Qt.AlignCenter + + horizontalAlignment: Text.AlignHCenter + verticalAlignment: Text.AlignVCenter + + selectByMouse: true + readOnly: true + font.pointSize: JamiTheme.textFontSize - 1 + text: textMetricsContactIdText.elidedText + + TextMetrics { + id: textMetricsContactIdText + font: contactId.font + text: idText + elideWidth: userProfileDialog.width - 30 + elide: Qt.ElideMiddle + } + } + + Image { + id: contactQrImage + + Layout.alignment: Qt.AlignBottom | Qt.AlignCenter + + width: 150 + height: 150 + + fillMode: Image.PreserveAspectFit + sourceSize.width: 150 + sourceSize.height: 150 + mipmap: true + } + } + + background: Rectangle { + border.width: 0 + radius: 10 + } + + onClosed: { + contactId.deselect() + fakeFocusTextEdit.focus = true + } + + onResponsibleConvUidChanged: { + if (responsibleConvUid !== "") + contactQrImage.source = "image://qrImage/contact_" + responsibleConvUid + } + + onContactPicBase64Changed: { + if (contactPicBase64 !== "") + contactImage.source = "data:image/png;base64," + contactPicBase64 + } +} diff --git a/src/mainview/components/VideoCallFullScreenWindowContainer.qml b/src/mainview/components/VideoCallFullScreenWindowContainer.qml new file mode 100644 index 00000000..c63e574f --- /dev/null +++ b/src/mainview/components/VideoCallFullScreenWindowContainer.qml @@ -0,0 +1,40 @@ + +/* + * Copyright (C) 2020 by Savoir-faire Linux + * Author: Mingrui Zhang + * + * 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 . + */ +import QtQuick 2.14 +import QtQuick.Window 2.14 + +Window { + id: videoWindow + + function setAsChild(obj) { + obj.parent = containerRect + } + + flags: Qt.FramelessWindowHint + + screen: Qt.application.screens[0] + + visible: false + + Rectangle { + id: containerRect + + anchors.fill: parent + } +} diff --git a/src/mainview/components/VideoCallPage.qml b/src/mainview/components/VideoCallPage.qml new file mode 100644 index 00000000..e1f29b9b --- /dev/null +++ b/src/mainview/components/VideoCallPage.qml @@ -0,0 +1,375 @@ + +/* + * Copyright (C) 2020 by Savoir-faire Linux + * Author: Mingrui Zhang + * + * 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 . + */ +import QtQuick 2.14 +import QtQuick.Controls 2.14 +import QtQuick.Layouts 1.14 +import QtQuick.Controls.Universal 2.12 +import QtGraphicalEffects 1.14 +import net.jami.Models 1.0 + +import "../../commoncomponents" + +Rectangle { + id: videoCallPageRect + + property string bestName: "Best Name" + property string bestId: "Best Id" + property variant clickPos: "1,1" + property int previewMargin: 15 + property int previewToX: 0 + property int previewToY: 0 + + property var corrspondingMessageWebView: null + + signal videoCallPageBackButtonIsClicked + signal needToShowInFullScreen + + function updateUI(accountId, convUid) { + bestName = ClientWrapper.utilsAdaptor.getBestName(accountId, convUid) + + var id = ClientWrapper.utilsAdaptor.getBestId(accountId, convUid) + bestId = (bestName !== id) ? id : "" + } + + function setDistantRendererId(id) { + distantRenderer.setRendererId(id) + } + + function setVideoCallPageCorrspondingMessageWebView(webViewId) { + corrspondingMessageWebView = webViewId + corrspondingMessageWebView.needToHideConversationInCall.disconnect( + closeInCallConversation) + corrspondingMessageWebView.needToHideConversationInCall.connect( + closeInCallConversation) + } + + function closeInCallConversation() { + if (inVideoCallMessageWebViewStack.visible) { + corrspondingMessageWebView.resetMessagingHeaderBackButtonSource( + true) + corrspondingMessageWebView.setMessagingHeaderButtonsVisible(true) + inVideoCallMessageWebViewStack.visible = false + inVideoCallMessageWebViewStack.clear() + } + } + + function closeContextMenuAndRelatedWindows() { + videoCallPageContextMenu.closePotentialWindows() + videoCallPageContextMenu.close() + videoCallOverlay.closePotentialContactPicker() + } + + function previewMagneticSnap() { + + + /* + * Calculate the position where the previewRenderer should attach to. + */ + var previewRendererCenter = Qt.point( + previewRenderer.x + previewRenderer.width / 2, + previewRenderer.y + previewRenderer.height / 2) + var distantRendererCenter = Qt.point( + distantRenderer.x + distantRenderer.width / 2, + distantRenderer.y + distantRenderer.height / 2) + + if (previewRendererCenter.x >= distantRendererCenter.x) { + if (previewRendererCenter.y >= distantRendererCenter.y) { + + + /* + * Bottom right. + */ + previewToX = Qt.binding(function () { + return videoCallPageMainRect.width - previewRenderer.width - previewMargin + }) + previewToY = Qt.binding(function () { + return videoCallPageMainRect.height - previewRenderer.height - previewMargin + }) + } else { + + + /* + * Top right. + */ + previewToX = Qt.binding(function () { + return videoCallPageMainRect.width - previewRenderer.width - previewMargin + }) + previewToY = previewMargin + } + } else { + if (previewRendererCenter.y >= distantRendererCenter.y) { + + + /* + * Bottom left. + */ + previewToX = previewMargin + previewToY = Qt.binding(function () { + return videoCallPageMainRect.height - previewRenderer.height - previewMargin + }) + } else { + + + /* + * Top left. + */ + previewToX = previewMargin + previewToY = previewMargin + } + } + previewRenderer.state = "geoChanging" + } + + function setCallOverlayBackButtonVisible(visible) { + videoCallOverlay.setBackTintedButtonVisible(visible) + } + + anchors.fill: parent + + SplitView { + id: mainColumnLayout + + anchors.fill: parent + + orientation: Qt.Vertical + + handle: Rectangle { + implicitWidth: videoCallPageRect.width + implicitHeight: JamiTheme.splitViewHandlePreferedWidth + color: SplitHandle.pressed ? JamiTheme.pressColor : (SplitHandle.hovered ? JamiTheme.hoverColor : JamiTheme.tabbarBorderColor) + } + + Rectangle { + id: videoCallPageMainRect + + SplitView.preferredHeight: (videoCallPageRect.height / 3) * 2 + SplitView.minimumHeight: videoCallPageRect.height / 2 + 20 + SplitView.fillWidth: true + + CallOverlay { + id: videoCallOverlay + + anchors.fill: parent + + Connections { + target: CallAdapter + + function onUpdateTimeText(time) { + videoCallOverlay.timeText = time + } + + function onUpdateOverlay(isPaused, isAudioOnly, isAudioMuted, isVideoMuted, isRecording, isSIP, isConferenceCall, bestName) { + videoCallOverlay.showOnHoldImage(isPaused) + videoCallOverlay.updateButtonStatus(isPaused, + isAudioOnly, + isAudioMuted, + isVideoMuted, + isRecording, isSIP, + isConferenceCall) + videoCallOverlay.bestName = bestName + } + + function onShowOnHoldLabel(isPaused) { + videoCallOverlay.showOnHoldImage(isPaused) + } + } + + onBackButtonIsClicked: { + if (inVideoCallMessageWebViewStack.visible) { + corrspondingMessageWebView.resetMessagingHeaderBackButtonSource( + true) + corrspondingMessageWebView.setMessagingHeaderButtonsVisible( + true) + inVideoCallMessageWebViewStack.visible = false + inVideoCallMessageWebViewStack.clear() + } + videoCallPageRect.videoCallPageBackButtonIsClicked() + } + + onOverlayChatButtonClicked: { + if (inVideoCallMessageWebViewStack.visible) { + corrspondingMessageWebView.resetMessagingHeaderBackButtonSource( + true) + corrspondingMessageWebView.setMessagingHeaderButtonsVisible( + true) + inVideoCallMessageWebViewStack.visible = false + inVideoCallMessageWebViewStack.clear() + } else { + corrspondingMessageWebView.resetMessagingHeaderBackButtonSource( + false) + corrspondingMessageWebView.setMessagingHeaderButtonsVisible( + false) + inVideoCallMessageWebViewStack.visible = true + inVideoCallMessageWebViewStack.push( + corrspondingMessageWebView) + } + } + } + + DistantRenderer { + id: distantRenderer + + anchors.centerIn: videoCallPageMainRect + z: -1 + + width: videoCallPageMainRect.width + height: videoCallPageMainRect.height + } + + VideoCallPreviewRenderer { + id: previewRenderer + + + /* + * Property is used in the {} expression for height (extra dependency), + * it will not affect the true height expression, since expression + * at last will be taken only, but it will force the height to update + * and reevaluate getPreviewImageScalingFactor(). + */ + property int previewImageScalingFactorUpdated: 0 + + Connections { + target: CallAdapter + + function onPreviewVisibilityNeedToChange(visible) { + previewRenderer.visible = visible + } + } + + width: videoCallPageMainRect.width / 4 + height: { + previewImageScalingFactorUpdated + return previewRenderer.width * previewRenderer.getPreviewImageScalingFactor() + } + x: videoCallPageMainRect.width - previewRenderer.width - previewMargin + y: videoCallPageMainRect.height - previewRenderer.height - previewMargin + z: -1 + + states: [ + State { + name: "geoChanging" + PropertyChanges { + target: previewRenderer + x: previewToX + y: previewToY + } + } + ] + + transitions: Transition { + PropertyAnimation { + properties: "x,y" + easing.type: Easing.OutExpo + duration: 250 + + onStopped: { + previewRenderer.state = "" + } + } + } + + MouseArea { + id: dragMouseArea + + anchors.fill: previewRenderer + + onPressed: { + clickPos = Qt.point(mouse.x, mouse.y) + } + + onReleased: { + previewRenderer.state = "" + previewMagneticSnap() + } + + onPositionChanged: { + + + /* + * Calculate mouse position relative change. + */ + var delta = Qt.point(mouse.x - clickPos.x, + mouse.y - clickPos.y) + var deltaW = previewRenderer.x + delta.x + previewRenderer.width + var deltaH = previewRenderer.y + delta.y + previewRenderer.height + + + /* + * Check if the previewRenderer exceeds the border of videoCallPageMainRect. + */ + if (deltaW < videoCallPageMainRect.width + && previewRenderer.x + delta.x > 1) + previewRenderer.x += delta.x + if (deltaH < videoCallPageMainRect.height + && previewRenderer.y + delta.y > 1) + previewRenderer.y += delta.y + } + } + + onPreviewImageAvailable: { + previewImageScalingFactorUpdated++ + previewImageScalingFactorUpdated-- + } + } + + color: "transparent" + } + + StackView { + id: inVideoCallMessageWebViewStack + + SplitView.preferredHeight: videoCallPageRect.height / 3 + SplitView.fillWidth: true + + visible: false + + clip: true + } + } + + VideoCallPageContextMenu { + id: videoCallPageContextMenu + + onFullScreenNeeded: { + videoCallPageRect.needToShowInFullScreen() + } + } + + MouseArea { + anchors.fill: parent + + propagateComposedEvents: true + acceptedButtons: Qt.RightButton + + onClicked: { + + + /* + * Make menu pos at mouse. + */ + var relativeMousePos = mapToItem(videoCallPageRect, + mouse.x, mouse.y) + videoCallPageContextMenu.x = relativeMousePos.x + videoCallPageContextMenu.y = relativeMousePos.y + videoCallPageContextMenu.activate() + } + } + + color: "black" +} diff --git a/src/mainview/components/VideoCallPageContextMenu.qml b/src/mainview/components/VideoCallPageContextMenu.qml new file mode 100644 index 00000000..642ec244 --- /dev/null +++ b/src/mainview/components/VideoCallPageContextMenu.qml @@ -0,0 +1,209 @@ + +/* + * Copyright (C) 2020 by Savoir-faire Linux + * Author: Mingrui Zhang + * + * 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 . + */ +import QtQuick 2.14 +import QtQuick.Controls 2.14 +import net.jami.Models 1.0 + +import "../../commoncomponents" + +import "../js/videodevicecontextmenuitemcreation.js" as VideoDeviceContextMenuItemCreation +import "../js/selectscreenwindowcreation.js" as SelectScreenWindowCreation +import "../js/screenrubberbandcreation.js" as ScreenRubberBandCreation + +Menu { + id: contextMenu + + property string responsibleAccountId: "" + property string responsibleConvUid: "" + + property int generalMenuSeparatorCount: 0 + property int commonBorderWidth: 2 + + signal fullScreenNeeded + + function activate() { + var deviceContextMenuInfoMap = AvAdapter.populateVideoDeviceContextMenuItem() + + + /* + * Somehow, the map size is undefined, so use this instead. + */ + var mapSize = deviceContextMenuInfoMap["size"] + + var count = 1 + for (var deviceName in deviceContextMenuInfoMap) { + if (deviceName === "size") + continue + if (videoDeviceItem.itemName === "No video device") { + videoDeviceItem.checkable = true + videoDeviceItem.itemName = deviceName + videoDeviceItem.checked = deviceContextMenuInfoMap[deviceName] + if (count === mapSize) + contextMenu.open() + } else { + VideoDeviceContextMenuItemCreation.createVideoDeviceContextMenuItemObjects( + deviceName, deviceContextMenuInfoMap[deviceName], + count === mapSize) + } + count++ + } + } + + function closePotentialWindows() { + SelectScreenWindowCreation.destorySelectScreenWindow() + ScreenRubberBandCreation.destoryScreenRubberBandWindow() + } + + implicitWidth: 200 + + JamiFileDialog { + id: jamiFileDialog + + mode: JamiFileDialog.Mode.OpenFile + + onAccepted: { + var filePath = jamiFileDialog.file + + + /* + * No need to trim file:///. + */ + AvAdapter.shareFile(filePath) + } + } + + + /* + * All GeneralMenuItems should remain the same width / height. + * The first videoDeviceItem is to make sure the border is correct. + */ + VideoCallPageContextMenuDeviceItem { + id: videoDeviceItem + + topBorderWidth: commonBorderWidth + contextMenuPreferredWidth: contextMenu.implicitWidth + } + + GeneralMenuSeparator { + preferredWidth: videoDeviceItem.preferredWidth + preferredHeight: commonBorderWidth + + Component.onCompleted: { + generalMenuSeparatorCount++ + } + } + + GeneralMenuItem { + id: shareEntireScreenItem + + itemName: qsTr("Share entire screen") + leftBorderWidth: commonBorderWidth + rightBorderWidth: commonBorderWidth + + onClicked: { + contextMenu.close() + if (Qt.application.screens.length === 1) { + AvAdapter.shareEntireScreen(0) + } else { + SelectScreenWindowCreation.createSelectScreenWindowObject() + SelectScreenWindowCreation.showSelectScreenWindow() + } + } + } + + GeneralMenuItem { + id: shareScreenAreaItem + + itemName: qsTr("Share screen area") + leftBorderWidth: commonBorderWidth + rightBorderWidth: commonBorderWidth + + onClicked: { + contextMenu.close() + if (Qt.application.screens.length === 1) { + ScreenRubberBandCreation.createScreenRubberBandWindowObject( + null, 0) + ScreenRubberBandCreation.showScreenRubberBandWindow() + } else { + SelectScreenWindowCreation.createSelectScreenWindowObject(true) + SelectScreenWindowCreation.showSelectScreenWindow() + } + } + } + + GeneralMenuItem { + id: shareFileItem + + itemName: qsTr("Share file") + leftBorderWidth: commonBorderWidth + rightBorderWidth: commonBorderWidth + + onClicked: { + contextMenu.close() + jamiFileDialog.open() + } + } + + GeneralMenuSeparator { + preferredWidth: videoDeviceItem.preferredWidth + preferredHeight: commonBorderWidth + + Component.onCompleted: { + generalMenuSeparatorCount++ + } + } + + GeneralMenuItem { + id: fullScreenItem + + property bool isFullScreen: false + + itemName: isFullScreen ? qsTr("Exit full screen") : qsTr( + "Full screen mode") + iconSource: isFullScreen ? "qrc:/images/icons/ic_exit_full_screen_black.png" : "qrc:/images/icons/ic_full_screen_black.png" + leftBorderWidth: commonBorderWidth + rightBorderWidth: commonBorderWidth + bottomBorderWidth: commonBorderWidth + + onClicked: { + contextMenu.close() + contextMenu.fullScreenNeeded() + isFullScreen = !isFullScreen + } + } + + onClosed: { + videoDeviceItem.itemName = "No video device" + VideoDeviceContextMenuItemCreation.removeCreatedItems() + } + + Component.onCompleted: { + VideoDeviceContextMenuItemCreation.setVideoContextMenuObject( + contextMenu) + } + + background: Rectangle { + implicitWidth: contextMenu.implicitWidth + implicitHeight: videoDeviceItem.preferredHeight + * (contextMenu.count - generalMenuSeparatorCount) + + border.width: commonBorderWidth + border.color: JamiTheme.tabbarBorderColor + } +} diff --git a/src/mainview/components/VideoCallPageContextMenuDeviceItem.qml b/src/mainview/components/VideoCallPageContextMenuDeviceItem.qml new file mode 100644 index 00000000..f94a9979 --- /dev/null +++ b/src/mainview/components/VideoCallPageContextMenuDeviceItem.qml @@ -0,0 +1,94 @@ + +/* + * Copyright (C) 2020 by Savoir-faire Linux + * Author: Mingrui Zhang + * + * 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 . + */ +import QtQuick 2.14 +import QtQuick.Controls 2.14 +import net.jami.Models 1.0 + +import "../../commoncomponents" + + +/* + * Take advantage of child can access parent's item (ex: contextMenu, commonBorderWidth). + */ +GeneralMenuItem { + id: videoCallPageContextMenuDeviceItem + + property int contextMenuPreferredWidth: 250 + + itemName: qsTr("No video device") + leftBorderWidth: commonBorderWidth + rightBorderWidth: commonBorderWidth + + TextMetrics { + id: textMetrics + font: deviceNameText.font + elide: Text.ElideMiddle + elideWidth: contextMenuPreferredWidth + - videoCallPageContextMenuDeviceItem.implicitIndicatorWidth + text: videoCallPageContextMenuDeviceItem.itemName + } + + contentItem: Text { + id: deviceNameText + + leftPadding: 30 + rightPadding: videoCallPageContextMenuDeviceItem.arrow.width + + horizontalAlignment: Text.AlignLeft + verticalAlignment: Text.AlignVCenter + + font.pointSize: JamiTheme.textFontSize - 3 + text: textMetrics.elidedText + } + + indicator: Item { + id: selectItem + + anchors.left: parent.left + anchors.verticalCenter: parent.verticalCenter + + implicitWidth: 32 + implicitHeight: 32 + + Rectangle { + id: selectRect + + width: selectItem.width / 2 + height: selectItem.height / 2 + anchors.centerIn: parent + visible: videoCallPageContextMenuDeviceItem.checkable + border.color: JamiTheme.selectionGreen + radius: 3 + Rectangle { + width: selectRect.width / 2 + height: selectRect.height / 2 + anchors.centerIn: parent + visible: videoCallPageContextMenuDeviceItem.checked + color: JamiTheme.selectionGreen + radius: 2 + } + } + } + + onClicked: { + var deviceName = videoCallPageContextMenuDeviceItem.itemName + contextMenu.close() + AvAdapter.onVideoContextMenuDeviceItemClicked(deviceName) + } +} diff --git a/src/mainview/components/WelcomePage.qml b/src/mainview/components/WelcomePage.qml new file mode 100644 index 00000000..a6250d00 --- /dev/null +++ b/src/mainview/components/WelcomePage.qml @@ -0,0 +1,234 @@ + +/* + * Copyright (C) 2020 by Savoir-faire Linux + * Author: Mingrui Zhang + * + * 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 . + */ +import QtQuick 2.14 +import QtQuick.Controls 2.14 +import QtQuick.Layouts 1.14 +import net.jami.Models 1.0 + +import "../../commoncomponents" + +Rectangle { + id: welcomeRect + + property int currentAccountIndex: 0 + property int buttonPreferredSize: 30 + + anchors.fill: parent + + Rectangle { + id: welcomeRectComponentsGroup + + anchors.centerIn: parent + + width: Math.max(welcomePageGroupPreferedWidth, welcomeRect.width - 100) + height: mainViewWindow.minimumHeight + + ColumnLayout { + id: welcomeRectComponentsGroupColumnLayout + + Image { + id: jamiLogoImage + + Layout.alignment: Qt.AlignCenter + Layout.preferredWidth: welcomeRectComponentsGroup.width + Layout.preferredHeight: 100 + Layout.topMargin: 50 + Layout.bottomMargin: 10 + + fillMode: Image.PreserveAspectFit + source: "qrc:/images/logo-jami-standard-coul.png" + mipmap: true + } + + Label { + id: jamiIntroText + + Layout.alignment: Qt.AlignCenter + Layout.preferredWidth: welcomeRectComponentsGroup.width + Layout.preferredHeight: 100 + Layout.bottomMargin: 5 + + wrapMode: Text.WordWrap + font.pointSize: JamiTheme.textFontSize + 1 + + horizontalAlignment: Text.AlignHCenter + verticalAlignment: Text.AlignVCenter + + text: qsTr("Jami is a free software for universal communication which repects the freedoms and privacy of its user.") + } + + Label { + id: jamiShareWithFriendText + + Layout.alignment: Qt.AlignCenter + Layout.preferredWidth: welcomeRectComponentsGroup.width + Layout.preferredHeight: 50 + + wrapMode: Text.WordWrap + font.pointSize: JamiTheme.textFontSize - 1 + + horizontalAlignment: Text.AlignHCenter + verticalAlignment: Text.AlignVCenter + + visible: accountListModel.data(accountListModel.index( + currentAccountIndex, 0), + 260) === 1 + text: qsTr("This is your ID.\nCopy and share it with your friends") + color: JamiTheme.faddedFontColor + } + + Rectangle { + id: jamiRegisteredNameRect + + Layout.alignment: Qt.AlignCenter + Layout.preferredWidth: welcomeRectComponentsGroup.width + Layout.preferredHeight: 65 + Layout.bottomMargin: 5 + + visible: accountListModel.data(accountListModel.index( + currentAccountIndex, 0), + 260) === 1 + + ColumnLayout { + id: jamiRegisteredNameRectColumnLayout + + spacing: 0 + + Text { + id: jamiRegisteredNameText + + Layout.alignment: Qt.AlignCenter + Layout.preferredWidth: welcomeRectComponentsGroup.width + Layout.preferredHeight: 30 + + font.pointSize: JamiTheme.textFontSize + + horizontalAlignment: Text.AlignHCenter + verticalAlignment: Text.AlignVCenter + + text: textMetricsjamiRegisteredNameText.elidedText + + TextMetrics { + id: textMetricsjamiRegisteredNameText + + font: jamiRegisteredNameText.font + text: accountListModel.data( + accountListModel.index( + currentAccountIndex, 0), 258) + elideWidth: welcomeRectComponentsGroup.width + elide: Qt.ElideMiddle + } + } + + RowLayout { + id: jamiRegisteredNameRowLayout + + Layout.alignment: Qt.AlignCenter + Layout.preferredWidth: buttonPreferredSize * 2 + 20 + Layout.preferredHeight: 30 + + HoverableButton { + id: copyRegisterednameButton + + Layout.alignment: Qt.AlignCenter + Layout.preferredWidth: buttonPreferredSize + Layout.preferredHeight: buttonPreferredSize + + radius: 30 + source: "qrc:/images/icons/ic_content_copy.svg" + + onClicked: { + ClientWrapper.utilsAdaptor.setText( + textMetricsjamiRegisteredNameText.text) + } + } + + HoverableButton { + id: qrCodeGenerateButton + + Layout.alignment: Qt.AlignCenter + Layout.preferredWidth: buttonPreferredSize + Layout.preferredHeight: buttonPreferredSize + + radius: 30 + source: "qrc:/images/qrcode.png" + + onClicked: { + qrDialog.open() + } + } + } + } + } + + Image { + id: sipImage + + Layout.alignment: Qt.AlignCenter + Layout.preferredWidth: 200 + Layout.preferredHeight: 200 + + + /* + * Check if account type is ring. + */ + visible: accountListModel.data(accountListModel.index( + currentAccountIndex, 0), + 260) === 1 ? false : true + fillMode: Image.PreserveAspectFit + + + /* + * Requested size. + */ + sourceSize.width: 200 + sourceSize.height: 200 + mipmap: true + } + } + + HoverableButton { + id: aboutButton + + anchors.horizontalCenter: welcomeRectComponentsGroup.horizontalCenter + anchors.bottom: welcomeRectComponentsGroup.bottom + anchors.bottomMargin: 5 + + width: 80 + height: buttonPreferredSize + + text: qsTr("About") + fontPointSize: JamiTheme.textFontSize + radius: 10 + + onClicked: { + aboutPopUpDialog.open() + } + } + } + + CustomBorder { + commonBorder: false + lBorderwidth: 1 + rBorderwidth: 0 + tBorderwidth: 0 + bBorderwidth: 0 + borderColor: JamiTheme.tabbarBorderColor + } +} diff --git a/src/mainview/components/WelcomePageQrDialog.qml b/src/mainview/components/WelcomePageQrDialog.qml new file mode 100644 index 00000000..45c8ff28 --- /dev/null +++ b/src/mainview/components/WelcomePageQrDialog.qml @@ -0,0 +1,61 @@ + +/* + * Copyright (C) 2020 by Savoir-faire Linux + * Author: Mingrui Zhang + * + * 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 . + */ +import QtQuick 2.14 +import QtQuick.Controls 2.14 +import QtQuick.Layouts 1.14 +import net.jami.Models 1.0 + +Dialog { + id: userQrImageDialog + + property int currentAccountIndex: 0 + + + /* + * When dialog is opened, trigger mainViewWindow overlay which is defined in overlay.model. + * (model : true is necessary) + */ + modal: true + + + /* + * Content height + margin. + */ + contentHeight: userQrImage.height + 30 + + Image { + id: userQrImage + + anchors.centerIn: parent + + width: 250 + height: 250 + + fillMode: Image.PreserveAspectFit + source: "image://qrImage/account_" + currentAccountIndex + sourceSize.width: 260 + sourceSize.height: 260 + mipmap: true + } + + background: Rectangle { + border.width: 0 + radius: 10 + } +} diff --git a/src/mainview/js/contactpickercreation.js b/src/mainview/js/contactpickercreation.js new file mode 100644 index 00000000..7ce7b62e --- /dev/null +++ b/src/mainview/js/contactpickercreation.js @@ -0,0 +1,80 @@ + +/* + * Copyright (C) 2020 by Savoir-faire Linux + * Author: Mingrui Zhang + * + * 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 . + */ + + +/* + * Global contact picker component, object variable for creation. + */ +var contactPickerComponent +var contactPickerObject + +function createContactPickerObjects(type, parent) { + if (contactPickerObject) { + + + /* + * If already created, reset parameters, since object cannot be destroyed. + */ + contactPickerObject.parent = parent + contactPickerObject.type = type + return + } + contactPickerComponent = Qt.createComponent( + "../components/ContactPicker.qml") + if (contactPickerComponent.status === Component.Ready) + finishCreation(type, parent) + else if (contactPickerComponent.status === Component.Error) + console.log("Error loading component:", + contactPickerComponent.errorString()) +} + +function finishCreation(type, parent) { + contactPickerObject = contactPickerComponent.createObject(parent, { + "type": type + }) + if (contactPickerObject === null) { + + + /* + * Error Handling. + */ + console.log("Error creating object for contact picker") + } +} + + +/* + * Put contact picker in the middle of container. + */ +function calculateCurrentGeo(containerX, containerY) { + if (contactPickerObject) { + contactPickerObject.x = containerX - contactPickerObject.width / 2 + contactPickerObject.y = containerY - contactPickerObject.height / 2 + } +} + +function openContactPicker() { + if (contactPickerObject) + contactPickerObject.open() +} + +function closeContactPicker() { + if (contactPickerObject) + contactPickerObject.close() +} diff --git a/src/mainview/js/incomingcallpagecreation.js b/src/mainview/js/incomingcallpagecreation.js new file mode 100644 index 00000000..6e0fcb0d --- /dev/null +++ b/src/mainview/js/incomingcallpagecreation.js @@ -0,0 +1,120 @@ + +/* + * Copyright (C) 2020 by Savoir-faire Linux + * Author: Mingrui Zhang + * + * 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 . + */ + + +/* + * Global incomingCallPage storage map>. + */ +let incomingCallPageWindowMap = new Map() + + +/* + * Global incomingCallPage component, object variable for creation. + */ +var incomingCallPageWindowComponent +var incomingCallPageWindowObject + +function createincomingCallPageWindowObjects(accountId, convUid) { + + + /* + * Check if the corrsponding call exists or not. + */ + if (incomingCallPageWindowMap.has(accountId)) { + if (incomingCallPageWindowMap.get(accountId).has(convUid)) { + return + } + } + + incomingCallPageWindowComponent = Qt.createComponent( + "../components/IncomingCallPage.qml") + if (incomingCallPageWindowComponent.status === Component.Ready) + finishCreation(accountId, convUid) + else if (incomingCallPageWindowComponent.status === Component.Error) + console.log("Error loading component:", + incomingCallPageWindowComponent.errorString()) +} + +function finishCreation(accountId, convUid) { + incomingCallPageWindowObject = incomingCallPageWindowComponent.createObject( + ) + if (incomingCallPageWindowObject === null) { + + + /* + * Error Handling. + */ + console.log("Error creating object for accountId" + accountId) + } + + incomingCallPageWindowObject.responsibleConvUid = convUid + incomingCallPageWindowObject.responsibleAccountId = accountId + incomingCallPageWindowObject.updateUI() + + + /* + * Record in map. + */ + if (incomingCallPageWindowMap.has(accountId)) { + incomingCallPageWindowMap.get(accountId).set( + convUid, incomingCallPageWindowObject) + } else { + let incomingCallPageWindowTempMap = new Map() + incomingCallPageWindowTempMap.set(convUid, incomingCallPageWindowObject) + incomingCallPageWindowMap.set(accountId, incomingCallPageWindowTempMap) + } +} + +function showIncomingCallPageWindow(accountId, convUid) { + if (incomingCallPageWindowMap.has(accountId)) { + if (incomingCallPageWindowMap.get(accountId).has(convUid)) { + if (!incomingCallPageWindowMap.get(accountId).get( + convUid).visible) { + incomingCallPageWindowMap.get(accountId).get(convUid).show() + incomingCallPageWindowMap.get(accountId).get( + convUid).updatePositionToRightBottom() + } + } + } +} + +function closeIncomingCallPageWindow(accountId, convUid) { + if (incomingCallPageWindowMap.has(accountId)) { + let incomingCallPageWindowTempMap = incomingCallPageWindowMap.get( + accountId) + if (incomingCallPageWindowTempMap.has(convUid)) { + var incomingCallPageWindow = incomingCallPageWindowTempMap.get( + convUid) + + + /* + * Close incomingCallPageWindow and clear the memory + */ + incomingCallPageWindow.close() + incomingCallPageWindow.destroy() + incomingCallPageWindowTempMap.delete(convUid) + if (incomingCallPageWindowTempMap.size === 0) { + incomingCallPageWindowMap.delete(accountId) + } else { + incomingCallPageWindowMap.set(accountId, + incomingCallPageWindowTempMap) + } + } + } +} diff --git a/src/mainview/js/screenrubberbandcreation.js b/src/mainview/js/screenrubberbandcreation.js new file mode 100644 index 00000000..38a22fdb --- /dev/null +++ b/src/mainview/js/screenrubberbandcreation.js @@ -0,0 +1,80 @@ + +/* + * Copyright (C) 2020 by Savoir-faire Linux + * Author: Mingrui Zhang + * + * 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 . + */ + + +/* + * Global screen rubber band window component, object variable for creation. + */ +var screenRubberBandWindowComponent +var screenRubberBandWindowObject + +function createScreenRubberBandWindowObject(parent, screenNumber) { + if (screenRubberBandWindowObject) + return + screenRubberBandWindowComponent = Qt.createComponent( + "../components/ScreenRubberBand.qml") + if (screenRubberBandWindowComponent.status === Component.Ready) + finishCreation(parent, screenNumber) + else if (screenRubberBandWindowComponent.status === Component.Error) + console.log("Error loading component:", + screenRubberBandWindowComponent.errorString()) +} + +function finishCreation(parent, screenNumber) { + screenRubberBandWindowObject = screenRubberBandWindowComponent.createObject( + parent) + if (screenRubberBandWindowObject === null) { + + + /* + * Error Handling. + */ + console.log("Error creating screen rubber band object") + } + + screenRubberBandWindowObject.screenNumber = screenNumber + screenRubberBandWindowObject.screen = Qt.application.screens[screenNumber] + + + /* + * Signal connection. + */ + screenRubberBandWindowObject.onClosing.connect( + destoryScreenRubberBandWindow) +} + +function showScreenRubberBandWindow() { + screenRubberBandWindowObject.showFullScreen() +} + + +/* + * Destroy and reset screenRubberBandWindowObject when window is closed. + */ +function destoryScreenRubberBandWindow() { + if (!screenRubberBandWindowObject) + return + screenRubberBandWindowObject.destroy() + screenRubberBandWindowObject = false +} + +function connectOnClosingEvent(func) { + if (screenRubberBandWindowObject) + screenRubberBandWindowObject.onClosing.connect(func) +} diff --git a/src/mainview/js/selectscreenwindowcreation.js b/src/mainview/js/selectscreenwindowcreation.js new file mode 100644 index 00000000..15bfbd15 --- /dev/null +++ b/src/mainview/js/selectscreenwindowcreation.js @@ -0,0 +1,72 @@ + +/* + * Copyright (C) 2020 by Savoir-faire Linux + * Author: Mingrui Zhang + * + * 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 . + */ + + +/* + * Global select screen window component, object variable for creation. + */ +var selectScreenWindowComponent +var selectScreenWindowObject + +function createSelectScreenWindowObject(selectArea = false) { + if (selectScreenWindowObject) + return + selectScreenWindowComponent = Qt.createComponent( + "../components/SelectScreen.qml") + if (selectScreenWindowComponent.status === Component.Ready) + finishCreation(selectArea) + else if (selectScreenWindowComponent.status === Component.Error) + console.log("Error loading component:", + selectScreenWindowComponent.errorString()) +} + +function finishCreation(selectArea) { + selectScreenWindowObject = selectScreenWindowComponent.createObject() + if (selectScreenWindowObject === null) { + + + /* + * Error Handling. + */ + console.log("Error creating select screen object") + } + + selectScreenWindowObject.selectArea = selectArea + + + /* + * Signal connection. + */ + selectScreenWindowObject.onClosing.connect(destorySelectScreenWindow) +} + +function showSelectScreenWindow() { + selectScreenWindowObject.show() +} + + +/* + * Destroy and reset selectScreenWindowObject when window is closed. + */ +function destorySelectScreenWindow() { + if(!selectScreenWindowObject) + return + selectScreenWindowObject.destroy() + selectScreenWindowObject = false +} diff --git a/src/mainview/js/videocallfullscreenwindowcontainercreation.js b/src/mainview/js/videocallfullscreenwindowcontainercreation.js new file mode 100644 index 00000000..23a51d7b --- /dev/null +++ b/src/mainview/js/videocallfullscreenwindowcontainercreation.js @@ -0,0 +1,97 @@ + +/* + * Copyright (C) 2020 by Savoir-faire Linux + * Author: Mingrui Zhang + * + * 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 . + */ + + +/* + * Global video call full screen window container, object variable for creation. + */ +var videoCallFullScreenWindowContainerComponent +var videoCallFullScreenWindowContainerObject + +function createvideoCallFullScreenWindowContainerObject() { + if (videoCallFullScreenWindowContainerObject) + return + videoCallFullScreenWindowContainerComponent = Qt.createComponent( + "../components/VideoCallFullScreenWindowContainer.qml") + if (videoCallFullScreenWindowContainerComponent.status === Component.Ready) + finishCreation() + else if (videoCallFullScreenWindowContainerComponent.status === Component.Error) + console.log("Error loading component:", + videoCallFullScreenWindowContainerComponent.errorString()) +} + +function finishCreation() { + videoCallFullScreenWindowContainerObject + = videoCallFullScreenWindowContainerComponent.createObject() + if (videoCallFullScreenWindowContainerObject === null) { + + + /* + * Error Handling. + */ + console.log("Error creating video call full screen window container object") + } + + + /* + * Signal connection. + */ + videoCallFullScreenWindowContainerObject.onClosing.connect( + destoryVideoCallFullScreenWindowContainer) +} + +function checkIfVisible() { + if (!videoCallFullScreenWindowContainerObject) + return false + return videoCallFullScreenWindowContainerObject.visible +} + +function setAsContainerChild(obj) { + if (videoCallFullScreenWindowContainerObject) + videoCallFullScreenWindowContainerObject.setAsChild(obj) +} + + +/* + * Destroy and reset videoCallFullScreenWindowContainerObject when window is closed. + */ +function destoryVideoCallFullScreenWindowContainer() { + if (!videoCallFullScreenWindowContainerObject) + return + videoCallFullScreenWindowContainerObject.destroy() + videoCallFullScreenWindowContainerObject = false +} + +function showVideoCallFullScreenWindowContainer() { + if (videoCallFullScreenWindowContainerObject) { + + + /* + * Hack: show first, then showFullScreen to make sure that the showFullScreen + * display on the correct screen. + */ + videoCallFullScreenWindowContainerObject.show() + videoCallFullScreenWindowContainerObject.showFullScreen() + } +} + +function closeVideoCallFullScreenWindowContainer() { + if (videoCallFullScreenWindowContainerObject) + videoCallFullScreenWindowContainerObject.close() +} diff --git a/src/mainview/js/videodevicecontextmenuitemcreation.js b/src/mainview/js/videodevicecontextmenuitemcreation.js new file mode 100644 index 00000000..2bab369a --- /dev/null +++ b/src/mainview/js/videodevicecontextmenuitemcreation.js @@ -0,0 +1,92 @@ + +/* + * Copyright (C) 2020 by Savoir-faire Linux + * Author: Mingrui Zhang + * + * 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 . + */ + + +/* + * Global storage for created video device context menu item, + * will be cleared once context menu is closed. + */ +var itemArray = [] + + +/* + * Global videoDeviceContextMenuItem component, object variable for creation. + */ +var videoContextMenuObject +var videoDeviceContextMenuItemComponent +var videoDeviceContextMenuItemObject + + +/* + * Init videoContextMenuObject. + */ +function setVideoContextMenuObject(obj) { + videoContextMenuObject = obj +} + +function createVideoDeviceContextMenuItemObjects(deviceName, setChecked, last) { + + videoDeviceContextMenuItemComponent = Qt.createComponent( + "../components/VideoCallPageContextMenuDeviceItem.qml") + if (videoDeviceContextMenuItemComponent.status === Component.Ready) + finishCreation(deviceName, setChecked, last) + else if (videoDeviceContextMenuItemComponent.status === Component.Error) + console.log("Error loading component:", + videoDeviceContextMenuItemComponent.errorString()) +} + +function finishCreation(deviceName, setChecked, last) { + videoDeviceContextMenuItemObject = videoDeviceContextMenuItemComponent.createObject() + if (videoDeviceContextMenuItemObject === null) { + + + /* + * Error Handling. + */ + console.log("Error creating video context menu object") + } + + videoDeviceContextMenuItemObject.itemName = deviceName + videoDeviceContextMenuItemObject.checkable = true + videoDeviceContextMenuItemObject.checked = setChecked + videoDeviceContextMenuItemObject.contextMenuPreferredWidth = videoContextMenuObject.implicitWidth + + + /* + * Push into the storage array, and insert it into context menu. + */ + itemArray.push(videoDeviceContextMenuItemObject) + videoContextMenuObject.insertItem(1, videoDeviceContextMenuItemObject) + + + /* + * If it is the last device context menu item, open the context menu. + */ + if (last) + videoContextMenuObject.open() +} + +function removeCreatedItems() { + var arrayLength = itemArray.length + for (var i = 0; i < arrayLength; i++) { + videoContextMenuObject.removeItem(itemArray[i]) + itemArray[i].destroy() + } + itemArray = [] +} diff --git a/src/messagesadapter.cpp b/src/messagesadapter.cpp new file mode 100644 index 00000000..1aa925be --- /dev/null +++ b/src/messagesadapter.cpp @@ -0,0 +1,657 @@ +/* + * Copyright (C) 2020 by Savoir-faire Linux + * Author: Edric Ladent Milaret + * Author: Anthony L�onard + * Author: Olivier Soldano + * Author: Andreas Traczyk + * Author: Isa Nanic + * Author: Mingrui Zhang + * + * 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 . + */ + +#include "messagesadapter.h" +#include "webchathelpers.h" + +#include "utils.h" + +#include +#include +#include +#include +#include + +MessagesAdapter::MessagesAdapter(QObject *parent) + : QmlAdapterBase(parent) +{} + +MessagesAdapter::~MessagesAdapter() {} + +void +MessagesAdapter::initQmlObject() +{ + connectConversationModel(); +} + +void +MessagesAdapter::setupChatView(const QString &uid) +{ + auto &convInfo = LRCInstance::getConversationFromConvUid(uid); + if (convInfo.uid.isEmpty()) { + return; + } + + QString contactURI = convInfo.participants.at(0); + + bool isContact = false; + auto selectedAccountId = LRCInstance::getCurrAccId(); + auto &accountInfo = LRCInstance::accountModel().getAccountInfo(selectedAccountId); + + lrc::api::profile::Type contactType; + try { + auto contactInfo = accountInfo.contactModel->getContact(contactURI); + if (contactInfo.isTrusted) { + isContact = true; + } + contactType = contactInfo.profileInfo.type; + } catch (...) { + } + + bool shouldShowSendContactRequestBtn = !isContact + && contactType != lrc::api::profile::Type::SIP; + + QMetaObject::invokeMethod(qmlObj_, + "setSendContactRequestButtonVisible", + Q_ARG(QVariant, shouldShowSendContactRequestBtn)); + + setMessagesVisibility(false); + + /* + * Type Indicator (contact). + */ + contactIsComposing(convInfo.uid, "", false); + connect(LRCInstance::getCurrentConversationModel(), + &ConversationModel::composingStatusChanged, + [this](const QString &uid, const QString &contactUri, bool isComposing) { + contactIsComposing(uid, contactUri, isComposing); + }); + + /* + * Draft and message content set up. + */ + Utils::oneShotConnect(qmlObj_, + SIGNAL(sendMessageContentSaved(const QString &)), + this, + SLOT(slotSendMessageContentSaved(const QString &))); + + requestSendMessageContent(); +} + +void +MessagesAdapter::connectConversationModel() +{ + auto currentConversationModel = LRCInstance::getCurrentAccountInfo().conversationModel.get(); + + QObject::disconnect(newInteractionConnection_); + QObject::disconnect(interactionRemovedConnection_); + QObject::disconnect(interactionStatusUpdatedConnection_); + + newInteractionConnection_ + = QObject::connect(currentConversationModel, + &lrc::api::ConversationModel::newInteraction, + [this](const QString &convUid, + uint64_t interactionId, + const lrc::api::interaction::Info &interaction) { + auto accountId = LRCInstance::getCurrAccId(); + newInteraction(accountId, convUid, interactionId, interaction); + }); + + interactionStatusUpdatedConnection_ = QObject::connect( + currentConversationModel, + &lrc::api::ConversationModel::interactionStatusUpdated, + [this](const QString &convUid, + uint64_t interactionId, + const lrc::api::interaction::Info &interaction) { + if (convUid != LRCInstance::getCurrentConvUid()) { + return; + } + auto ¤tAccountInfo = LRCInstance::getCurrentAccountInfo(); + auto currentConversationModel = currentAccountInfo.conversationModel.get(); + currentConversationModel->clearUnreadInteractions(convUid); + updateInteraction(*currentConversationModel, interactionId, interaction); + }); + + interactionRemovedConnection_ + = QObject::connect(currentConversationModel, + &lrc::api::ConversationModel::interactionRemoved, + [this](const QString &convUid, uint64_t interactionId) { + Q_UNUSED(convUid); + removeInteraction(interactionId); + }); + + currentConversationModel->setFilter(""); +} + +void +MessagesAdapter::sendContactRequest() +{ + auto convInfo = LRCInstance::getCurrentConversation(); + if (!convInfo.uid.isEmpty()) { + LRCInstance::getCurrentConversationModel()->makePermanent(convInfo.uid); + } +} + +void +MessagesAdapter::accountChangedSetUp(const QString &accoountId) +{ + Q_UNUSED(accoountId) + + connectConversationModel(); +} + +void +MessagesAdapter::updateConversationForAddedContact() +{ + auto conversation = LRCInstance::getCurrentConversation(); + auto convModel = LRCInstance::getCurrentConversationModel(); + + clear(); + setConversationProfileData(conversation); + printHistory(*convModel, conversation.interactions); +} + +void +MessagesAdapter::slotSendMessageContentSaved(const QString &content) +{ + if (!LastConvUid_.isEmpty()) { + LRCInstance::setContentDraft(LastConvUid_, LRCInstance::getCurrAccId(), content); + } + LastConvUid_ = LRCInstance::getCurrentConvUid(); + + Utils::oneShotConnect(qmlObj_, SIGNAL(messagesCleared()), this, SLOT(slotMessagesCleared())); + + setInvitation(false); + clear(); + auto restoredContent = LRCInstance::getContentDraft(LRCInstance::getCurrentConvUid(), + LRCInstance::getCurrAccId()); + setSendMessageContent(restoredContent); + emit needToUpdateSmartList(); +} + +void +MessagesAdapter::slotUpdateDraft(const QString &content) +{ + if (!LastConvUid_.isEmpty()) { + LRCInstance::setContentDraft(LastConvUid_, LRCInstance::getCurrAccId(), content); + } + emit needToUpdateSmartList(); +} + +void +MessagesAdapter::slotMessagesCleared() +{ + auto &convInfo = LRCInstance::getConversationFromConvUid(LRCInstance::getCurrentConvUid()); + auto convModel = LRCInstance::getCurrentConversationModel(); + + printHistory(*convModel, convInfo.interactions); + + Utils::oneShotConnect(qmlObj_, SIGNAL(messagesLoaded()), this, SLOT(slotMessagesLoaded())); + + setConversationProfileData(convInfo); +} + +void +MessagesAdapter::slotMessagesLoaded() +{ + setMessagesVisibility(true); +} + +void +MessagesAdapter::sendMessage(const QString &message) +{ + try { + auto convUid = LRCInstance::getCurrentConvUid(); + LRCInstance::getCurrentConversationModel()->sendMessage(convUid, message); + } catch (...) { + qDebug() << "Exception during sendMessage:" << message; + } +} + +void +MessagesAdapter::sendImage(const QString &message) +{ + if (message.startsWith("data:image/png;base64,")) { + /* + * Img tag contains base64 data, trim "data:image/png;base64," from data. + */ + QByteArray data = QByteArray::fromStdString(message.toStdString().substr(22)); + auto img_name_hash = QString::fromStdString( + QCryptographicHash::hash(data, QCryptographicHash::Sha1).toHex().toStdString()); + QString fileName = "\\img_" + img_name_hash + ".png"; + + QPixmap image_to_save; + if (!image_to_save.loadFromData(QByteArray::fromBase64(data))) { + qDebug().noquote() << "Errors during loadFromData" + << "\n"; + } + + QString path = QString(Utils::WinGetEnv("TEMP")) + fileName; + if (!image_to_save.save(path, "PNG")) { + qDebug().noquote() << "Errors during QPixmap save" + << "\n"; + } + + try { + auto convUid = LRCInstance::getCurrentConvUid(); + LRCInstance::getCurrentConversationModel()->sendFile(convUid, path, fileName); + } catch (...) { + qDebug().noquote() << "Exception during sendFile - base64 img" + << "\n"; + } + + } else { + /* + * Img tag contains file paths. + */ + + QString msg(message); +#ifdef Q_OS_WIN + msg = msg.replace("file:///", ""); +#else + msg = msg.replace("file:///", "/"); +#endif + QFileInfo fi(msg); + QString fileName = fi.fileName(); + + try { + auto convUid = LRCInstance::getCurrentConvUid(); + LRCInstance::getCurrentConversationModel()->sendFile(convUid, msg, fileName); + } catch (...) { + qDebug().noquote() << "Exception during sendFile - image from path" + << "\n"; + } + } +} + +void +MessagesAdapter::sendFile(const QString &message) +{ + QFileInfo fi(message); + QString fileName = fi.fileName(); + try { + auto convUid = LRCInstance::getCurrentConvUid(); + LRCInstance::getCurrentConversationModel()->sendFile(convUid, message, fileName); + } catch (...) { + qDebug() << "Exception during sendFile"; + } +} + +void +MessagesAdapter::retryInteraction(const QString &arg) +{ + bool ok; + uint64_t interactionUid = arg.toULongLong(&ok); + if (ok) { + LRCInstance::getCurrentConversationModel() + ->retryInteraction(LRCInstance::getCurrentConvUid(), interactionUid); + } else { + qDebug() << "retryInteraction - invalid arg" << arg; + } +} + +void +MessagesAdapter::setNewMessagesContent(const QString &path) +{ + if (path.length() == 0) + return; + QByteArray imageFormat = QImageReader::imageFormat(path); + + if (!imageFormat.isEmpty()) { + setMessagesImageContent(path); + } else { + setMessagesFileContent(path); + } +} + +void +MessagesAdapter::deleteInteraction(const QString &arg) +{ + bool ok; + uint64_t interactionUid = arg.toULongLong(&ok); + if (ok) { + LRCInstance::getCurrentConversationModel() + ->clearInteractionFromConversation(LRCInstance::getCurrentConvUid(), interactionUid); + } else { + qDebug() << "DeleteInteraction - invalid arg" << arg; + } +} + +void +MessagesAdapter::openFile(const QString &arg) +{ + QUrl fileUrl("file:///" + arg); + if (!QDesktopServices::openUrl(fileUrl)) { + qDebug() << "Couldn't open file: " << fileUrl; + } +} + +void +MessagesAdapter::acceptFile(const QString &arg) +{ + try { + auto interactionUid = arg.toLongLong(); + auto convUid = LRCInstance::getCurrentConvUid(); + LRCInstance::getCurrentConversationModel()->acceptTransfer(convUid, interactionUid); + } catch (...) { + qDebug() << "JS bridging - exception during acceptFile: " << arg; + } +} + +void +MessagesAdapter::refuseFile(const QString &arg) +{ + try { + auto interactionUid = arg.toLongLong(); + auto convUid = LRCInstance::getCurrentConvUid(); + LRCInstance::getCurrentConversationModel()->cancelTransfer(convUid, interactionUid); + } catch (...) { + qDebug() << "JS bridging - exception during refuseFile:" << arg; + } +} + +void +MessagesAdapter::pasteKeyDetected() +{ + const QMimeData *mimeData = QApplication::clipboard()->mimeData(); + + if (mimeData->hasImage()) { + /* + * Save temp data into base64 format. + */ + QPixmap pixmap = qvariant_cast(mimeData->imageData()); + QByteArray ba; + QBuffer bu(&ba); + bu.open(QIODevice::WriteOnly); + pixmap.save(&bu, "PNG"); + auto str = QString::fromLocal8Bit(ba.toBase64()); + + setMessagesImageContent(str, true); + } else if (mimeData->hasUrls()) { + QList urlList = mimeData->urls(); + /* + * Extract the local paths of the files. + */ + for (int i = 0; i < urlList.size(); ++i) { + /* + * Trim file:/// from url. + */ + QString filePath = urlList.at(i).toString().remove(0, 8); + QByteArray imageFormat = QImageReader::imageFormat(filePath); + + /* + * Check if file is qt supported image file type. + */ + if (!imageFormat.isEmpty()) { + setMessagesImageContent(filePath); + } else { + setMessagesFileContent(filePath); + } + } + } else { + QMetaObject::invokeMethod(qmlObj_, + "webViewRunJavaScript", + Q_ARG(QVariant, + QStringLiteral("replaceText(`%1`)").arg(mimeData->text()))); + } +} + +void +MessagesAdapter::onComposing(bool isComposing) +{ + LRCInstance::getCurrentConversationModel()->setIsComposing(LRCInstance::getCurrentConvUid(), + isComposing); +} + +void +MessagesAdapter::setConversationProfileData(const lrc::api::conversation::Info &convInfo) +{ + auto convModel = LRCInstance::getCurrentConversationModel(); + auto accInfo = &LRCInstance::getCurrentAccountInfo(); + auto contactUri = convInfo.participants.front(); + + if (contactUri.isEmpty()) { + return; + } + try { + auto &contact = accInfo->contactModel->getContact(contactUri); + auto bestName = Utils::bestNameForConversation(convInfo, *convModel); + setInvitation(contact.profileInfo.type == lrc::api::profile::Type::PENDING, + bestName, + contactUri); + + if (!contact.profileInfo.avatar.isEmpty()) { + setSenderImage(contactUri, contact.profileInfo.avatar); + } else { + auto avatar = Utils::conversationPhoto(convInfo.uid, *accInfo, true); + QByteArray ba; + QBuffer bu(&ba); + avatar.save(&bu, "PNG"); + setSenderImage(contactUri, QString::fromLocal8Bit(ba.toBase64())); + } + } catch (...) { + } +} + +void +MessagesAdapter::newInteraction(const QString &accountId, + const QString &convUid, + uint64_t interactionId, + const interaction::Info &interaction) +{ + Q_UNUSED(interactionId); + try { + auto &accountInfo = LRCInstance::getAccountInfo(accountId); + auto &convModel = accountInfo.conversationModel; + auto &conversation = LRCInstance::getConversationFromConvUid(convUid, accountId); + + if (conversation.uid.isEmpty()) { + return; + } + if (!interaction.authorUri.isEmpty() + && (!QApplication::focusWindow() || LRCInstance::getCurrAccId() != accountId)) { + /* + * TODO: Notification from other accounts. + */ + } + if (convUid != LRCInstance::getCurrentConvUid()) { + return; + } + convModel->clearUnreadInteractions(convUid); + printNewInteraction(*convModel, interactionId, interaction); + } catch (...) { + } +} + +void +MessagesAdapter::updateDraft() +{ + Utils::oneShotConnect(qmlObj_, + SIGNAL(sendMessageContentSaved(const QString &)), + this, + SLOT(slotUpdateDraft(const QString &))); + + requestSendMessageContent(); +} + +/* + * JS invoke. + */ +void +MessagesAdapter::setMessagesVisibility(bool visible) +{ + QString s = QString::fromLatin1(visible ? "showMessagesDiv();" : "hideMessagesDiv();"); + QMetaObject::invokeMethod(qmlObj_, "webViewRunJavaScript", Q_ARG(QVariant, s)); +} + +void +MessagesAdapter::requestSendMessageContent() +{ + QString s = QString::fromLatin1("requestSendMessageContent();"); + QMetaObject::invokeMethod(qmlObj_, "webViewRunJavaScript", Q_ARG(QVariant, s)); +} + +void +MessagesAdapter::setInvitation(bool show, const QString &contactUri, const QString &contactId) +{ + QString s + = show + ? QString::fromLatin1("showInvitation(\"%1\", \"%2\")").arg(contactUri).arg(contactId) + : QString::fromLatin1("showInvitation()"); + + QMetaObject::invokeMethod(qmlObj_, "webViewRunJavaScript", Q_ARG(QVariant, s)); +} + +void +MessagesAdapter::clear() +{ + QString s = QString::fromLatin1("clearMessages();"); + QMetaObject::invokeMethod(qmlObj_, "webViewRunJavaScript", Q_ARG(QVariant, s)); +} + +void +MessagesAdapter::printHistory(lrc::api::ConversationModel &conversationModel, + const std::map interactions) +{ + auto interactionsStr = interactionsToJsonArrayObject(conversationModel, interactions).toUtf8(); + QString s = QString::fromLatin1("printHistory(%1);").arg(interactionsStr.constData()); + QMetaObject::invokeMethod(qmlObj_, "webViewRunJavaScript", Q_ARG(QVariant, s)); +} + +void +MessagesAdapter::setSenderImage(const QString &sender, const QString &senderImage) +{ + QJsonObject setSenderImageObject = QJsonObject(); + setSenderImageObject.insert("sender_contact_method", QJsonValue(sender)); + setSenderImageObject.insert("sender_image", QJsonValue(senderImage)); + + auto setSenderImageObjectString = QString( + QJsonDocument(setSenderImageObject).toJson(QJsonDocument::Compact)); + QString s = QString::fromLatin1("setSenderImage(%1);") + .arg(setSenderImageObjectString.toUtf8().constData()); + QMetaObject::invokeMethod(qmlObj_, "webViewRunJavaScript", Q_ARG(QVariant, s)); +} + +void +MessagesAdapter::printNewInteraction(lrc::api::ConversationModel &conversationModel, + uint64_t msgId, + const lrc::api::interaction::Info &interaction) +{ + auto interactionObject + = interactionToJsonInteractionObject(conversationModel, msgId, interaction).toUtf8(); + if (interactionObject.isEmpty()) { + return; + } + QString s = QString::fromLatin1("addMessage(%1);").arg(interactionObject.constData()); + QMetaObject::invokeMethod(qmlObj_, "webViewRunJavaScript", Q_ARG(QVariant, s)); +} + +void +MessagesAdapter::updateInteraction(lrc::api::ConversationModel &conversationModel, + uint64_t msgId, + const lrc::api::interaction::Info &interaction) +{ + auto interactionObject + = interactionToJsonInteractionObject(conversationModel, msgId, interaction).toUtf8(); + if (interactionObject.isEmpty()) { + return; + } + QString s = QString::fromLatin1("updateMessage(%1);").arg(interactionObject.constData()); + QMetaObject::invokeMethod(qmlObj_, "webViewRunJavaScript", Q_ARG(QVariant, s)); +} + +void +MessagesAdapter::setMessagesImageContent(const QString &path, bool isBased64) +{ + if (isBased64) { + QString param = QString("addImage_base64('file://%1')").arg(path); + QMetaObject::invokeMethod(qmlObj_, "webViewRunJavaScript", Q_ARG(QVariant, param)); + } else { + QString param = QString("addImage_path('file://%1')").arg(path); + QMetaObject::invokeMethod(qmlObj_, "webViewRunJavaScript", Q_ARG(QVariant, param)); + } +} + +void +MessagesAdapter::setMessagesFileContent(const QString &path) +{ + qint64 fileSize = QFileInfo(path).size(); + QString fileName = QFileInfo(path).fileName(); + /* + * If file name is too large, trim it. + */ + if (fileName.length() > 15) { + fileName = fileName.remove(12, fileName.length() - 12) + "..."; + } + QString param = QString("addFile_path('%1','%2','%3')") + .arg(path, fileName, Utils::humanFileSize(fileSize)); + + QMetaObject::invokeMethod(qmlObj_, "webViewRunJavaScript", Q_ARG(QVariant, param)); +} + +void +MessagesAdapter::removeInteraction(uint64_t interactionId) +{ + QString s = QString::fromLatin1("removeInteraction(%1);").arg(QString::number(interactionId)); + QMetaObject::invokeMethod(qmlObj_, "webViewRunJavaScript", Q_ARG(QVariant, s)); +} + +void +MessagesAdapter::setSendMessageContent(const QString &content) +{ + QString s = QString::fromLatin1("setSendMessageContent(`%1`);").arg(content); + QMetaObject::invokeMethod(qmlObj_, "webViewRunJavaScript", Q_ARG(QVariant, s)); +} + +void +MessagesAdapter::contactIsComposing(const QString &uid, const QString &contactUri, bool isComposing) +{ + if (LRCInstance::getCurrentConvUid() == uid) { + QString s + = QString::fromLatin1("showTypingIndicator(`%1`, %2);").arg(contactUri).arg(isComposing); + QMetaObject::invokeMethod(qmlObj_, "webViewRunJavaScript", Q_ARG(QVariant, s)); + } +} + +void +MessagesAdapter::acceptInvitation() +{ + auto convUid = LRCInstance::getCurrentConvUid(); + LRCInstance::getCurrentConversationModel()->makePermanent(convUid); +} + +void +MessagesAdapter::refuseInvitation() +{ + auto convUid = LRCInstance::getCurrentConvUid(); + LRCInstance::getCurrentConversationModel()->removeConversation(convUid, false); + setInvitation(false); +} + +void +MessagesAdapter::blockConversation() +{ + auto convUid = LRCInstance::getCurrentConvUid(); + LRCInstance::getCurrentConversationModel()->removeConversation(convUid, true); + setInvitation(false); +} diff --git a/src/messagesadapter.h b/src/messagesadapter.h new file mode 100644 index 00000000..f3247661 --- /dev/null +++ b/src/messagesadapter.h @@ -0,0 +1,111 @@ +/* + * Copyright (C) 2020 by Savoir-faire Linux + * Author: Mingrui Zhang + * + * 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 . + */ + +#pragma once + +#include "lrcinstance.h" +#include "qmladapterbase.h" + +#include +#include + +class MessagesAdapter : public QmlAdapterBase +{ + Q_OBJECT + +public: + explicit MessagesAdapter(QObject *parent = 0); + ~MessagesAdapter(); + + Q_INVOKABLE void setupChatView(const QString &uid); + Q_INVOKABLE void connectConversationModel(); + Q_INVOKABLE void sendContactRequest(); + Q_INVOKABLE void accountChangedSetUp(const QString &accoountId); + Q_INVOKABLE void updateConversationForAddedContact(); + + /* + * JS Q_INVOKABLE. + */ + Q_INVOKABLE void acceptInvitation(); + Q_INVOKABLE void refuseInvitation(); + Q_INVOKABLE void blockConversation(); + Q_INVOKABLE void setNewMessagesContent(const QString &path); + Q_INVOKABLE void sendMessage(const QString &message); + Q_INVOKABLE void sendImage(const QString &message); + Q_INVOKABLE void sendFile(const QString &message); + Q_INVOKABLE void retryInteraction(const QString &arg); + Q_INVOKABLE void deleteInteraction(const QString &arg); + Q_INVOKABLE void openFile(const QString &arg); + Q_INVOKABLE void acceptFile(const QString &arg); + Q_INVOKABLE void refuseFile(const QString &arg); + Q_INVOKABLE void pasteKeyDetected(); + Q_INVOKABLE void onComposing(bool isComposing); + + /* + * Manually update draft when hiding message web view (Back to welcome page). + */ + Q_INVOKABLE void updateDraft(); + + /* + * Run corrsponding js functions, c++ to qml. + */ + void setMessagesVisibility(bool visible); + void requestSendMessageContent(); + void setInvitation(bool show, const QString &contactUri = "", const QString &contactId = ""); + void clear(); + void printHistory(lrc::api::ConversationModel &conversationModel, + const std::map interactions); + void setSenderImage(const QString &sender, const QString &senderImage); + void printNewInteraction(lrc::api::ConversationModel &conversationModel, + uint64_t msgId, + const lrc::api::interaction::Info &interaction); + void updateInteraction(lrc::api::ConversationModel &conversationModel, + uint64_t msgId, + const lrc::api::interaction::Info &interaction); + void setMessagesImageContent(const QString &path, bool isBased64 = false); + void setMessagesFileContent(const QString &path); + void removeInteraction(uint64_t interactionId); + void setSendMessageContent(const QString &content); + void contactIsComposing(const QString &uid, const QString &contactUri, bool isComposing); + +signals: + void needToUpdateSmartList(); + +public slots: + void slotSendMessageContentSaved(const QString &content); + void slotUpdateDraft(const QString &content); + void slotMessagesCleared(); + void slotMessagesLoaded(); + +private: + void initQmlObject() override final; + void setConversationProfileData(const lrc::api::conversation::Info &convInfo); + void newInteraction(const QString &accountId, + const QString &convUid, + uint64_t interactionId, + const interaction::Info &interaction); + + QString LastConvUid_; + + /* + * Interaction connections. + */ + QMetaObject::Connection newInteractionConnection_; + QMetaObject::Connection interactionStatusUpdatedConnection_; + QMetaObject::Connection interactionRemovedConnection_; +}; \ No newline at end of file diff --git a/src/pixbufmanipulator.cpp b/src/pixbufmanipulator.cpp new file mode 100644 index 00000000..e621808e --- /dev/null +++ b/src/pixbufmanipulator.cpp @@ -0,0 +1,131 @@ +/* + * Copyright (C) 2015-2020 by Savoir-faire Linux + * Author: Edric Ladent Milaret + * Author: Anthony Léonard + * Author: Olivier Soldano + * Author: Andreas Traczyk + * + * 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 . + */ + +#include "pixbufmanipulator.h" + +#include +#include +#include +#include +#include +#include +#include + +#include "globalinstances.h" + +#include +#include +#include +#include + +#include "utils.h" +#undef interface + +QVariant +PixbufManipulator::personPhoto(const QByteArray &data, const QString &type) +{ + QImage avatar; + const bool ret = avatar.loadFromData(QByteArray::fromBase64(data), type.toLatin1()); + if (!ret) { + qDebug() << "vCard image loading failed"; + return QVariant(); + } + return QPixmap::fromImage(Utils::getCirclePhoto(avatar, avatar.size().width())); +} + +QVariant +PixbufManipulator::numberCategoryIcon(const QVariant &p, + const QSize &size, + bool displayPresence, + bool isPresent) +{ + Q_UNUSED(p) + Q_UNUSED(size) + Q_UNUSED(displayPresence) + Q_UNUSED(isPresent) + return QVariant(); +} + +QByteArray +PixbufManipulator::toByteArray(const QVariant &pxm) +{ + auto image = pxm.value(); + QByteArray ba = Utils::QImageToByteArray(image); + return ba; +} + +QVariant +PixbufManipulator::userActionIcon(const UserActionElement &state) const +{ + Q_UNUSED(state) + return QVariant(); +} + +QVariant +PixbufManipulator::decorationRole(const QModelIndex &index) +{ + Q_UNUSED(index) + return QVariant(); +} + +QVariant +PixbufManipulator::decorationRole(const lrc::api::conversation::Info &conversationInfo, + const lrc::api::account::Info &accountInfo) +{ + QImage photo; + auto contacts = conversationInfo.participants; + if (contacts.empty()) { + return QVariant::fromValue(photo); + } + try { + /* + * Get first contact photo. + */ + auto contactUri = contacts.front(); + auto contactInfo = accountInfo.contactModel->getContact(contactUri); + auto contactPhoto = contactInfo.profileInfo.avatar; + auto bestName = Utils::bestNameForContact(contactInfo); + auto bestId = Utils::bestIdForContact(contactInfo); + if (accountInfo.profileInfo.type == lrc::api::profile::Type::SIP + && contactInfo.profileInfo.type == lrc::api::profile::Type::TEMPORARY) { + photo = Utils::fallbackAvatar(IMAGE_SIZE, QString(), QString()); + } else if (contactInfo.profileInfo.type == lrc::api::profile::Type::TEMPORARY + && contactInfo.profileInfo.uri.isEmpty()) { + photo = Utils::fallbackAvatar(IMAGE_SIZE, QString(), QString()); + } else if (!contactPhoto.isEmpty()) { + QByteArray byteArray = contactPhoto.toLocal8Bit(); + photo = personPhoto(byteArray, nullptr).value(); + if (photo.isNull()) { + auto avatarName = contactInfo.profileInfo.uri == bestName ? QString() : bestName; + photo = Utils::fallbackAvatar(IMAGE_SIZE, + "ring:" + contactInfo.profileInfo.uri, + avatarName); + } + } else { + auto avatarName = contactInfo.profileInfo.uri == bestName ? QString() : bestName; + photo = Utils::fallbackAvatar(IMAGE_SIZE, + "ring:" + contactInfo.profileInfo.uri, + avatarName); + } + } catch (...) { + } + return QVariant::fromValue(Utils::scaleAndFrame(photo, IMAGE_SIZE)); +} \ No newline at end of file diff --git a/src/pixbufmanipulator.h b/src/pixbufmanipulator.h new file mode 100644 index 00000000..5325f15b --- /dev/null +++ b/src/pixbufmanipulator.h @@ -0,0 +1,49 @@ +/* + * Copyright (C) 2015-2020 by Savoir-faire Linux + * Author: Edric Ladent Milaret + * + * 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 . + */ + +#pragma once + +#include + +#include +#include + +Q_DECLARE_METATYPE(QImage); + +class Person; + +QByteArray QImageToByteArray(QImage image); + +class PixbufManipulator : public Interfaces::PixmapManipulatorI +{ +public: + QVariant personPhoto(const QByteArray &data, const QString &type = "PNG") override; + + /* + * TODO: the following methods return an empty QVariant/QByteArray. + */ + QVariant numberCategoryIcon(const QVariant &p, + const QSize &size, + bool displayPresence = false, + bool isPresent = false) override; + QByteArray toByteArray(const QVariant &pxm) override; + QVariant userActionIcon(const UserActionElement &state) const override; + QVariant decorationRole(const QModelIndex &index) override; + QVariant decorationRole(const lrc::api::conversation::Info &conversation, + const lrc::api::account::Info &accountInfo) override; +}; diff --git a/src/pluginitemlistmodel.cpp b/src/pluginitemlistmodel.cpp new file mode 100644 index 00000000..dcc072f8 --- /dev/null +++ b/src/pluginitemlistmodel.cpp @@ -0,0 +1,123 @@ +/* + * Copyright (C) 2019-2020 by Savoir-faire Linux + * Author: Yang Wang + * + * 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 . + */ + +#include "pluginitemlistmodel.h" + +PluginItemListModel::PluginItemListModel(QObject *parent) + : QAbstractListModel(parent) +{} + +PluginItemListModel::~PluginItemListModel() {} + +int +PluginItemListModel::rowCount(const QModelIndex &parent) const +{ + if (!parent.isValid()) { + /* + * Count. + */ + return LRCInstance::pluginModel().listAvailablePlugins().size(); + } + /* + * A valid QModelIndex returns 0 as no entry has sub-elements. + */ + return 0; +} + +int +PluginItemListModel::columnCount(const QModelIndex &parent) const +{ + Q_UNUSED(parent); + /* + * Only need one column. + */ + return 1; +} + +QVariant +PluginItemListModel::data(const QModelIndex &index, int role) const +{ + auto pluginList = LRCInstance::pluginModel().listAvailablePlugins(); + if (!index.isValid() || pluginList.size() <= index.row()) { + return QVariant(); + } + + auto details = LRCInstance::pluginModel().getPluginDetails(pluginList.at(index.row())); + + switch (role) { + case Role::PluginName: + return QVariant(details.name); + case Role::PluginId: + return QVariant(pluginList.at(index.row())); + case Role::PluginIcon: + return QVariant(details.iconPath); + case Role::IsLoaded: + return QVariant(details.loaded); + } + return QVariant(); +} + +QHash +PluginItemListModel::roleNames() const +{ + QHash roles; + roles[PluginName] = "PluginName"; + roles[PluginId] = "PluginId"; + roles[PluginIcon] = "PluginIcon"; + roles[IsLoaded] = "IsLoaded"; + + return roles; +} + +QModelIndex +PluginItemListModel::index(int row, int column, const QModelIndex &parent) const +{ + Q_UNUSED(parent); + if (column != 0) { + return QModelIndex(); + } + + if (row >= 0 && row < rowCount()) { + return createIndex(row, column); + } + return QModelIndex(); +} + +QModelIndex +PluginItemListModel::parent(const QModelIndex &child) const +{ + Q_UNUSED(child); + return QModelIndex(); +} + +Qt::ItemFlags +PluginItemListModel::flags(const QModelIndex &index) const +{ + auto flags = QAbstractItemModel::flags(index) | Qt::ItemNeverHasChildren | Qt::ItemIsSelectable; + if (!index.isValid()) { + return QAbstractItemModel::flags(index); + } + return flags; +} + +void +PluginItemListModel::reset() +{ + beginResetModel(); + endResetModel(); +} diff --git a/src/pluginitemlistmodel.h b/src/pluginitemlistmodel.h new file mode 100644 index 00000000..da399f7c --- /dev/null +++ b/src/pluginitemlistmodel.h @@ -0,0 +1,56 @@ +/* + * Copyright (C) 2019-2020 by Savoir-faire Linux + * Author: Yang Wang + * + * 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 . + */ + +#pragma once + +#include + +#include "api/pluginmodel.h" + +#include "lrcinstance.h" + +class PluginItemListModel : public QAbstractListModel +{ + Q_OBJECT + +public: + enum Role { PluginName = Qt::UserRole + 1, PluginId, PluginIcon, IsLoaded }; + Q_ENUM(Role) + + explicit PluginItemListModel(QObject *parent = 0); + ~PluginItemListModel(); + + /* + * QAbstractListModel override. + */ + int rowCount(const QModelIndex &parent = QModelIndex()) const override; + int columnCount(const QModelIndex &parent) const override; + QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override; + /* + * Override role name as access point in qml. + */ + QHash roleNames() const override; + QModelIndex index(int row, int column = 0, const QModelIndex &parent = QModelIndex()) const; + QModelIndex parent(const QModelIndex &child) const; + Qt::ItemFlags flags(const QModelIndex &index) const; + + /* + * This function is to reset the model when there's new account added. + */ + Q_INVOKABLE void reset(); +}; diff --git a/src/preferenceitemlistmodel.cpp b/src/preferenceitemlistmodel.cpp new file mode 100644 index 00000000..8e90426e --- /dev/null +++ b/src/preferenceitemlistmodel.cpp @@ -0,0 +1,153 @@ +/* + * Copyright (C) 2019-2020 by Savoir-faire Linux + * Author: Yang Wang + * + * 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 . + */ + +#include "preferenceitemlistmodel.h" +#include + +std::map mapType {{QString("List"), PreferenceItemListModel::Type::LIST}}; + +PreferenceItemListModel::PreferenceItemListModel(QObject *parent) + : QAbstractListModel(parent) +{} + +PreferenceItemListModel::~PreferenceItemListModel() {} + +int +PreferenceItemListModel::rowCount(const QModelIndex &parent) const +{ + if (!parent.isValid()) { + /* + * Count. + */ + return LRCInstance::pluginModel().getPluginPreferences(pluginId_).size(); + } + /* + * A valid QModelIndex returns 0 as no entry has sub-elements. + */ + return 0; +} + +int +PreferenceItemListModel::columnCount(const QModelIndex &parent) const +{ + Q_UNUSED(parent); + /* + * Only need one column. + */ + return 1; +} + +QVariant +PreferenceItemListModel::data(const QModelIndex &index, int role) const +{ + auto preferenceList = LRCInstance::pluginModel().getPluginPreferences(pluginId_); + if (!index.isValid() || preferenceList.size() <= index.row()) { + return QVariant(); + } + + auto details = preferenceList.at(index.row()); + int type = Type::DEFAULT; + auto it = mapType.find(details["type"]); + if (it != mapType.end()) + { + type = mapType[details["type"]]; + } + + switch (role) { + case Role::PreferenceKey: + return QVariant(details["key"]); + case Role::PreferenceName: + return QVariant(details["title"]); + case Role::PreferenceSummary: + return QVariant(details["summary"]); + case Role::PreferenceType: + return QVariant(type); + case Role::PreferenceDefaultValue: + return QVariant(details["defaultValue"]); + case Role::PreferenceEntries: + return QVariant(details["entries"]); + case Role::PreferenceEntryValues: + return QVariant(details["entryValues"]); + } + return QVariant(); +} + +QHash +PreferenceItemListModel::roleNames() const +{ + QHash roles; + roles[PreferenceKey] = "PreferenceKey"; + roles[PreferenceName] = "PreferenceName"; + roles[PreferenceSummary] = "PreferenceSummary"; + roles[PreferenceType] = "PreferenceType"; + roles[PreferenceDefaultValue] = "PreferenceDefaultValue"; + roles[PreferenceEntries] = "PreferenceEntries"; + roles[PreferenceEntryValues] = "PreferenceEntryValues"; + + return roles; +} + +QModelIndex +PreferenceItemListModel::index(int row, int column, const QModelIndex &parent) const +{ + Q_UNUSED(parent); + if (column != 0) { + return QModelIndex(); + } + + if (row >= 0 && row < rowCount()) { + return createIndex(row, column); + } + return QModelIndex(); +} + +QModelIndex +PreferenceItemListModel::parent(const QModelIndex &child) const +{ + Q_UNUSED(child); + return QModelIndex(); +} + +Qt::ItemFlags +PreferenceItemListModel::flags(const QModelIndex &index) const +{ + auto flags = QAbstractItemModel::flags(index) | Qt::ItemNeverHasChildren | Qt::ItemIsSelectable; + if (!index.isValid()) { + return QAbstractItemModel::flags(index); + } + return flags; +} + +void +PreferenceItemListModel::reset() +{ + beginResetModel(); + endResetModel(); +} + +QString +PreferenceItemListModel::pluginId() const +{ + return pluginId_; +} + +void +PreferenceItemListModel::setPluginId(const QString &pluginId) +{ + pluginId_ = pluginId; +} diff --git a/src/preferenceitemlistmodel.h b/src/preferenceitemlistmodel.h new file mode 100644 index 00000000..c51a0701 --- /dev/null +++ b/src/preferenceitemlistmodel.h @@ -0,0 +1,70 @@ +/* + * Copyright (C) 2019-2020 by Savoir-faire Linux + * Author: Yang Wang + * + * 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 . + */ + +#pragma once + +#include + +#include "api/pluginmodel.h" + +#include "lrcinstance.h" + +class PreferenceItemListModel : public QAbstractListModel +{ + Q_OBJECT + + Q_PROPERTY(QString pluginId READ pluginId WRITE setPluginId) +public: + enum Role { PreferenceKey = Qt::UserRole + 1, PreferenceName, PreferenceSummary, PreferenceType, PreferenceDefaultValue, PreferenceEntries, PreferenceEntryValues}; + + typedef enum { + LIST, + DEFAULT, + } Type; + + Q_ENUM(Role) + + explicit PreferenceItemListModel(QObject *parent = 0); + ~PreferenceItemListModel(); + + /* + * QAbstractListModel override. + */ + int rowCount(const QModelIndex &parent = QModelIndex()) const override; + int columnCount(const QModelIndex &parent) const override; + QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override; + /* + * Override role name as access point in qml. + */ + QHash roleNames() const override; + QModelIndex index(int row, int column = 0, const QModelIndex &parent = QModelIndex()) const; + QModelIndex parent(const QModelIndex &child) const; + Qt::ItemFlags flags(const QModelIndex &index) const; + + /* + * This function is to reset the model when there's new account added. + */ + Q_INVOKABLE void reset(); + + QString pluginId() const; + void setPluginId(const QString &pluginId); +// signals: +// void pluginIdChanged(); +private: + QString pluginId_; +}; diff --git a/src/previewrenderer.cpp b/src/previewrenderer.cpp new file mode 100644 index 00000000..773b23fd --- /dev/null +++ b/src/previewrenderer.cpp @@ -0,0 +1,146 @@ +/* + * Copyright (C) 2020 by Savoir-faire Linux + * Author: Andreas Traczyk + * Author: Mingrui Zhang + * + * 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 . + */ + +#include "previewrenderer.h" + +#include "lrcinstance.h" + +PreviewRenderer::PreviewRenderer(QQuickItem *parent) + : QQuickPaintedItem(parent) +{ + setAntialiasing(true); + setFillColor(Qt::black); + setRenderTarget(QQuickPaintedItem::FramebufferObject); + setPerformanceHint(QQuickPaintedItem::FastFBOResizing); + + previewFrameUpdatedConnection_ = connect(LRCInstance::renderer(), + &RenderManager::previewFrameUpdated, + [this]() { update(QRect(0, 0, width(), height())); }); + previewRenderingStopped_ = connect(LRCInstance::renderer(), + &RenderManager::previewRenderingStopped, + [this]() { update(QRect(0, 0, width(), height())); }); +} + +PreviewRenderer::~PreviewRenderer() +{ + disconnect(previewFrameUpdatedConnection_); + disconnect(previewRenderingStopped_); +} + +void +PreviewRenderer::paint(QPainter *painter) +{ + auto previewImage = LRCInstance::renderer()->getPreviewFrame(); + if (previewImage) { + QImage scaledPreview; + auto aspectRatio = static_cast(previewImage->width()) + / static_cast(previewImage->height()); + auto previewHeight = height(); + auto previewWidth = previewHeight * aspectRatio; + + /* Instead of setting fixed size, we could get an x offset for the preview + * but this would render the horizontal spacers in the parent widget useless. + * e.g. + * auto parent = qobject_cast(this->parent()); + * auto xPos = (parent->width() - previewWidth) / 2; + * setGeometry(QRect(QPoint(xPos, this->pos().y()), QSize(previewWidth, previewHeight))); + */ + setWidth(previewWidth); + setHeight(previewHeight); + + scaledPreview = previewImage->scaled(size().toSize(), Qt::KeepAspectRatio); + painter->drawImage(QRect(0, 0, scaledPreview.width(), scaledPreview.height()), + scaledPreview); + } +} + +VideoCallPreviewRenderer::VideoCallPreviewRenderer(QQuickItem *parent) + : PreviewRenderer(parent) +{} + +VideoCallPreviewRenderer::~VideoCallPreviewRenderer() {} + +qreal +VideoCallPreviewRenderer::getPreviewImageScalingFactor() +{ + auto previewImage = LRCInstance::renderer()->getPreviewFrame(); + if (previewImage) { + return static_cast(previewImage->height()) + / static_cast(previewImage->width()); + } + return 1.0; +} + +void +VideoCallPreviewRenderer::paint(QPainter *painter) +{ + auto previewImage = LRCInstance::renderer()->getPreviewFrame(); + + if (previewImage) { + emit previewImageAvailable(); + + QImage scaledPreview; + scaledPreview = previewImage->scaled(size().toSize(), Qt::KeepAspectRatio); + painter->drawImage(QRect(0, 0, scaledPreview.width(), scaledPreview.height()), + scaledPreview); + } +} + +PhotoboothPreviewRender::PhotoboothPreviewRender(QQuickItem *parent) + : PreviewRenderer(parent) +{ + connect(LRCInstance::renderer(), &RenderManager::previewRenderingStopped, [this]() { + emit hideBooth(); + }); +} + +PhotoboothPreviewRender::~PhotoboothPreviewRender() {} + +QImage +PhotoboothPreviewRender::takePhoto() +{ + if (auto previewImage = LRCInstance::renderer()->getPreviewFrame()) { + return previewImage->copy(); + } + return QImage(); +} + +QString +PhotoboothPreviewRender::takeCroppedPhotoToBase64(int size) +{ + auto image = Utils::cropImage(takePhoto()); + auto avatar = image.scaled(size, size, Qt::KeepAspectRatioByExpanding, Qt::SmoothTransformation); + + return QString::fromLatin1(Utils::QImageToByteArray(avatar).toBase64().data()); +} + +void +PhotoboothPreviewRender::paint(QPainter *painter) +{ + painter->setRenderHint(QPainter::Antialiasing, true); + + auto previewImage = LRCInstance::renderer()->getPreviewFrame(); + if (previewImage) { + QImage scaledPreview; + scaledPreview = Utils::getCirclePhoto(*previewImage, + height() <= width() ? height() : width()); + painter->drawImage(QRect(0, 0, scaledPreview.width(), scaledPreview.height()), + scaledPreview); + } +} diff --git a/src/previewrenderer.h b/src/previewrenderer.h new file mode 100644 index 00000000..408416c2 --- /dev/null +++ b/src/previewrenderer.h @@ -0,0 +1,74 @@ +/* + * Copyright (C) 2020 by Savoir-faire Linux + * Author: Andreas Traczyk + * Author: Mingrui Zhang + * + * 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 . + */ + +#pragma once + +#include + +/* + * Use QQuickPaintedItem so that QPainter apis can be used. + * Note: Old video pipeline. + */ +class PreviewRenderer : public QQuickPaintedItem +{ + Q_OBJECT +public: + explicit PreviewRenderer(QQuickItem *parent = 0); + ~PreviewRenderer(); + +protected: + void paint(QPainter *painter) override; + +private: + QMetaObject::Connection previewFrameUpdatedConnection_; + QMetaObject::Connection previewRenderingStopped_; +}; + +class VideoCallPreviewRenderer : public PreviewRenderer +{ + Q_OBJECT +public: + explicit VideoCallPreviewRenderer(QQuickItem *parent = 0); + virtual ~VideoCallPreviewRenderer(); + + Q_INVOKABLE qreal getPreviewImageScalingFactor(); + +signals: + void previewImageAvailable(); + +private: + void paint(QPainter *painter) override final; +}; + +class PhotoboothPreviewRender : public PreviewRenderer +{ + Q_OBJECT +public: + explicit PhotoboothPreviewRender(QQuickItem *parent = 0); + virtual ~PhotoboothPreviewRender(); + + QImage takePhoto(); + Q_INVOKABLE QString takeCroppedPhotoToBase64(int size); + +signals: + void hideBooth(); + +private: + void paint(QPainter *painter) override final; +}; diff --git a/src/qmladapterbase.cpp b/src/qmladapterbase.cpp new file mode 100644 index 00000000..6b8d3f68 --- /dev/null +++ b/src/qmladapterbase.cpp @@ -0,0 +1,35 @@ +/* + * Copyright (C) 2020 by Savoir-faire Linux + * Author: Mingrui Zhang + * + * 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 . + */ + +#include "qmladapterbase.h" + +QmlAdapterBase::QmlAdapterBase(QObject *parent) + : QObject(parent) +{ + qmlObj_ = nullptr; +} + +QmlAdapterBase::~QmlAdapterBase() {} + +void +QmlAdapterBase::setQmlObject(QObject *obj) +{ + qmlObj_ = obj; + + initQmlObject(); +} diff --git a/src/qmladapterbase.h b/src/qmladapterbase.h new file mode 100644 index 00000000..e476359e --- /dev/null +++ b/src/qmladapterbase.h @@ -0,0 +1,50 @@ +/* + * Copyright (C) 2020 by Savoir-faire Linux + * Author: Mingrui Zhang + * + * 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 . + */ + +#pragma once + +#include + +/* + * The main purpose of this class is to operate on qml objects, + * or provide api calls to qml objects that cannot be done directly in qml. + */ +class QmlAdapterBase : public QObject +{ + Q_OBJECT +public: + explicit QmlAdapterBase(QObject *parent = nullptr); + ~QmlAdapterBase(); + + /* + * This function should be called in the Component.onCompleted slot + * in the qml component that this adapter should attach to. + */ + Q_INVOKABLE void setQmlObject(QObject *obj); + +protected: + /* + *Once the qml object is set, custom actions can be done in this function. + */ + virtual void initQmlObject() = 0; + + /* + * Object pointer. + */ + QObject *qmlObj_; +}; diff --git a/src/qrimageprovider.h b/src/qrimageprovider.h new file mode 100644 index 00000000..cc8837eb --- /dev/null +++ b/src/qrimageprovider.h @@ -0,0 +1,93 @@ +/* + * Copyright (C) 2020 by Savoir-faire Linux + * Author: Mingrui Zhang + * + * 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 . + */ + +#pragma once + +#include "accountlistmodel.h" +#include "lrcinstance.h" + +#include +#include +#include +#include +#include + +class QrImageProvider : public QObject, public QQuickImageProvider +{ +public: + QrImageProvider() + : QQuickImageProvider(QQuickImageProvider::Image, + QQmlImageProviderBase::ForceAsynchronousImageLoading) + {} + + enum class QrType { Account, Contact }; + + /* + * Id should be string like account_0 (account index), + * or contact_xxx (uid). + * Cannot use getCurrentAccId to replace account index, + * since we need to keep each image id unique. + */ + QPair + getIndexFromID(const QString &id) + { + auto list = id.split('_', QString::SkipEmptyParts); + if (list.contains("account")) { + return QPair(QrType::Account, list[1]); + } else if (list.contains("contact") && list.size() > 1) { + /* + * For contact_xxx, xxx is "" initially + */ + auto convInfo = LRCInstance::getConversationFromConvUid(list[1]); + auto contact = LRCInstance::getCurrentAccountInfo().contactModel->getContact( + convInfo.participants.at(0)); + return QPair(QrType::Contact, contact.profileInfo.uri); + } + return QPair(QrType::Account, ""); + } + + QImage + requestImage(const QString &id, QSize *size, const QSize &requestedSize) override + { + Q_UNUSED(size); + + QString uri; + auto indexPair = getIndexFromID(id); + + if (indexPair.first == QrType::Contact) { + uri = indexPair.second; + } else { + if (indexPair.second.isEmpty()) + return QImage(); + + auto accountList = LRCInstance::accountModel().getAccountList(); + auto accountIndex = indexPair.second.toInt(); + if (accountList.size() <= accountIndex) + return QImage(); + + auto &accountInfo = LRCInstance::accountModel().getAccountInfo( + accountList.at(accountIndex)); + uri = accountInfo.profileInfo.uri; + } + + if (!requestedSize.isEmpty()) + return Utils::setupQRCode(uri, 0).scaled(requestedSize, Qt::KeepAspectRatio); + else + return Utils::setupQRCode(uri, 0); + } +}; \ No newline at end of file diff --git a/src/rendermanager.cpp b/src/rendermanager.cpp new file mode 100644 index 00000000..dfd095bb --- /dev/null +++ b/src/rendermanager.cpp @@ -0,0 +1,374 @@ +/* + * Copyright (C) 2019-2020 by Savoir-faire Linux + * Author: Andreas Traczyk + * Author: Mingrui Zhang + * + * 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 . + */ + +#include "rendermanager.h" + +#include + +#include + +using namespace lrc::api; + +FrameWrapper::FrameWrapper(AVModel &avModel, const QString &id) + : avModel_(avModel) + , id_(id) + , isRendering_(false) +{} + +FrameWrapper::~FrameWrapper() +{ + if (id_ == video::PREVIEW_RENDERER_ID) { + avModel_.stopPreview(); + } +} + +void +FrameWrapper::connectStartRendering() +{ + QObject::disconnect(renderConnections_.started); + renderConnections_.started = QObject::connect(&avModel_, + &AVModel::rendererStarted, + this, + &FrameWrapper::slotRenderingStarted); +} + +bool +FrameWrapper::startRendering() +{ + try { + renderer_ = const_cast(&avModel_.getRenderer(id_)); + } catch (std::out_of_range &e) { + qWarning() << e.what(); + return false; + } + + QObject::disconnect(renderConnections_.updated); + QObject::disconnect(renderConnections_.stopped); + + renderConnections_.updated = QObject::connect(&avModel_, + &AVModel::frameUpdated, + this, + &FrameWrapper::slotFrameUpdated); + + renderConnections_.stopped = QObject::connect(&avModel_, + &AVModel::rendererStopped, + this, + &FrameWrapper::slotRenderingStopped); + + return true; +} + +QImage * +FrameWrapper::getFrame() +{ + return image_.get(); +} + +bool +FrameWrapper::isRendering() +{ + return isRendering_; +} + +void +FrameWrapper::slotRenderingStarted(const QString &id) +{ + if (id != id_) { + return; + } + + if (!startRendering()) { + qWarning() << "Couldn't start rendering for id: " << id_; + return; + } + + isRendering_ = true; + + emit renderingStarted(id); +} + +void +FrameWrapper::slotFrameUpdated(const QString &id) +{ + if (id != id_) { + return; + } + + if (!renderer_ || !renderer_->isRendering()) { + return; + } + + { + QMutexLocker lock(&mutex_); + + frame_ = renderer_->currentFrame(); + + unsigned int width = renderer_->size().width(); + unsigned int height = renderer_->size().height(); + +#ifndef Q_OS_LINUX + unsigned int size = frame_.storage.size(); + /* + * If the frame is empty or not the expected size, + * do nothing and keep the last rendered QImage. + */ + if (size != 0 && size == width * height * 4) { + buffer_ = std::move(frame_.storage); + image_.reset(new QImage((uchar *) buffer_.data(), + width, + height, + QImage::Format_ARGB32_Premultiplied)); +#else + if (frame_.ptr) { + image_.reset(new QImage(frame_.ptr, width, height, QImage::Format_ARGB32)); +#endif + } + } + + emit frameUpdated(id); +} + +void +FrameWrapper::slotRenderingStopped(const QString &id) +{ + if (id != id_) { + return; + } + + QObject::disconnect(renderConnections_.updated); + QObject::disconnect(renderConnections_.stopped); + renderer_ = nullptr; + + /* + * The object's QImage pointer is reset before renderingStopped + * is emitted, allowing the listener to invoke specific behavior + * like clearing the widget or changing the UI entirely. + */ + image_.reset(); + + isRendering_ = false; + + emit renderingStopped(id); +} + +RenderManager::RenderManager(AVModel &avModel) + : avModel_(avModel) +{ + deviceListSize_ = avModel_.getDevices().size(); + connect(&avModel_, &lrc::api::AVModel::deviceEvent, this, &RenderManager::slotDeviceEvent); + + previewFrameWrapper_ = std::make_unique(avModel_); + + QObject::connect(previewFrameWrapper_.get(), + &FrameWrapper::renderingStarted, + [this](const QString &id) { + Q_UNUSED(id); + emit previewRenderingStarted(); + }); + QObject::connect(previewFrameWrapper_.get(), + &FrameWrapper::frameUpdated, + [this](const QString &id) { + Q_UNUSED(id); + emit previewFrameUpdated(); + }); + QObject::connect(previewFrameWrapper_.get(), + &FrameWrapper::renderingStopped, + [this](const QString &id) { + Q_UNUSED(id); + emit previewRenderingStopped(); + }); + + previewFrameWrapper_->connectStartRendering(); +} + +RenderManager::~RenderManager() +{ + previewFrameWrapper_.reset(); + + for (auto &dfw : distantFrameWrapperMap_) { + dfw.second.reset(); + } +} + +bool +RenderManager::isPreviewing() +{ + return previewFrameWrapper_->isRendering(); +} + +QImage * +RenderManager::getPreviewFrame() +{ + return previewFrameWrapper_->getFrame(); +} + +void +RenderManager::stopPreviewing(bool async) +{ + if (!previewFrameWrapper_->isRendering()) { + return; + } + + if (async) { + QtConcurrent::run([this] { avModel_.stopPreview(); }); + } else { + avModel_.stopPreview(); + } +} + +void +RenderManager::startPreviewing(bool force, bool async) +{ + if (previewFrameWrapper_->isRendering() && !force) { + return; + } + + auto restart = [this] { + if (previewFrameWrapper_->isRendering()) { + avModel_.stopPreview(); + } + avModel_.startPreview(); + }; + if (async) { + QtConcurrent::run(restart); + } else { + restart(); + } +} + +QImage * +RenderManager::getFrame(const QString &id) +{ + auto dfwIt = distantFrameWrapperMap_.find(id); + if (dfwIt != distantFrameWrapperMap_.end()) { + return dfwIt->second->getFrame(); + } + return nullptr; +} + +void +RenderManager::addDistantRenderer(const QString &id) +{ + /* + * Check if a FrameWrapper with this id exists. + */ + auto dfwIt = distantFrameWrapperMap_.find(id); + if (dfwIt != distantFrameWrapperMap_.end()) { + if (!dfwIt->second->startRendering()) { + qWarning() << "Couldn't start rendering for id: " << id; + } + } else { + auto dfw = std::make_unique(avModel_, id); + + /* + * Connect this to the FrameWrapper. + */ + distantConnectionMap_[id].started = QObject::connect(dfw.get(), + &FrameWrapper::renderingStarted, + [this](const QString &id) { + emit distantRenderingStarted(id); + }); + distantConnectionMap_[id].updated = QObject::connect(dfw.get(), + &FrameWrapper::frameUpdated, + [this](const QString &id) { + emit distantFrameUpdated(id); + }); + distantConnectionMap_[id].stopped = QObject::connect(dfw.get(), + &FrameWrapper::renderingStopped, + [this](const QString &id) { + emit distantRenderingStopped(id); + }); + + /* + * Connect FrameWrapper to avmodel. + */ + dfw->connectStartRendering(); + + /* + * Add to map. + */ + distantFrameWrapperMap_.insert(std::make_pair(id, std::move(dfw))); + } +} + +void +RenderManager::removeDistantRenderer(const QString &id) +{ + auto dfwIt = distantFrameWrapperMap_.find(id); + if (dfwIt != distantFrameWrapperMap_.end()) { + /* + * Disconnect FrameWrapper from this. + */ + auto dcIt = distantConnectionMap_.find(id); + if (dcIt != distantConnectionMap_.end()) { + QObject::disconnect(dcIt->second.started); + QObject::disconnect(dcIt->second.updated); + QObject::disconnect(dcIt->second.stopped); + } + + /* + * Erase. + */ + distantFrameWrapperMap_.erase(dfwIt); + } +} + +void +RenderManager::slotDeviceEvent() +{ + auto defaultDevice = avModel_.getDefaultDevice(); + auto currentCaptureDevice = avModel_.getCurrentVideoCaptureDevice(); + /* + * Decide whether a device has plugged, unplugged, or nothing has changed. + */ + auto deviceList = avModel_.getDevices(); + auto currentDeviceListSize = deviceList.size(); + + DeviceEvent deviceEvent{DeviceEvent::None}; + if (currentDeviceListSize > deviceListSize_) { + deviceEvent = DeviceEvent::Added; + } else if (currentDeviceListSize < deviceListSize_) { + /* + * Check if the currentCaptureDevice is still in the device list. + */ + if (std::find(std::begin(deviceList), std::end(deviceList), currentCaptureDevice) + == std::end(deviceList)) { + deviceEvent = DeviceEvent::RemovedCurrent; + } + } + + if (previewFrameWrapper_->isRendering()) { + if (currentDeviceListSize == 0) { + avModel_.clearCurrentVideoCaptureDevice(); + avModel_.switchInputTo({}); + stopPreviewing(); + } else if (deviceEvent == DeviceEvent::RemovedCurrent && currentDeviceListSize > 0) { + avModel_.setCurrentVideoCaptureDevice(defaultDevice); + startPreviewing(true); + } else { + startPreviewing(); + } + } else if (deviceEvent == DeviceEvent::Added && currentDeviceListSize == 1) { + avModel_.setCurrentVideoCaptureDevice(defaultDevice); + } + + emit videoDeviceListChanged(); + + deviceListSize_ = currentDeviceListSize; +} diff --git a/src/rendermanager.h b/src/rendermanager.h new file mode 100644 index 00000000..edb6017e --- /dev/null +++ b/src/rendermanager.h @@ -0,0 +1,282 @@ +/* + * Copyright (C) 2019-2020 by Savoir-faire Linux + * Author: Andreas Traczyk + * Author: Mingrui Zhang + * + * 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 . + */ + +#pragma once + +#include "api/avmodel.h" +#include "api/lrc.h" + +#include +#include +#include + +using namespace lrc::api; + +/* + * This class acts as a QImage rendering sink and manages + * signal/slot connections to it's underlying (AVModel) renderer + * corresponding to the object's renderer id. + * A QImage pointer is provisioned and updated once rendering + * starts. + */ + +struct RenderConnections +{ + QMetaObject::Connection started, stopped, updated; +}; + +class FrameWrapper final : public QObject +{ + Q_OBJECT; + +public: + FrameWrapper(AVModel &avModel, const QString &id = video::PREVIEW_RENDERER_ID); + ~FrameWrapper(); + + /* + * Reconnect the started rendering connection for this object. + */ + void connectStartRendering(); + + /* + * Get a pointer to the renderer and reconnect the update/stopped + * rendering connections for this object. + * @return whether the start succeeded or not + */ + bool startRendering(); + + /* + * Get the most recently rendered frame as a QImage. + * @return the rendered image of this object's id + */ + QImage *getFrame(); + + /* + * Check if the object is updating actively. + */ + bool isRendering(); + +signals: + /* + * Emitted once in slotRenderingStarted. + * @param id of the renderer + */ + void renderingStarted(const QString &id); + /* + * Emitted each time a frame is ready to be displayed. + * @param id of the renderer + */ + void frameUpdated(const QString &id); + /* + * Emitted once in slotRenderingStopped. + * @param id of the renderer + */ + void renderingStopped(const QString &id); + +private slots: + /* + * Used to listen to AVModel::rendererStarted. + * @param id of the renderer + */ + void slotRenderingStarted(const QString &id = video::PREVIEW_RENDERER_ID); + /* + * Used to listen to AVModel::frameUpdated. + * @param id of the renderer + */ + void slotFrameUpdated(const QString &id = video::PREVIEW_RENDERER_ID); + /* + * Used to listen to AVModel::renderingStopped. + * @param id of the renderer + */ + void slotRenderingStopped(const QString &id = video::PREVIEW_RENDERER_ID); + +private: + /* + * The id of the renderer. + */ + QString id_; + + /* + * A pointer to the lrc renderer object. + */ + video::Renderer *renderer_; + + /* + * A local copy of the renderer's current frame. + */ + video::Frame frame_; + + /* + * A the frame's storage data used to set the image. + */ + std::vector buffer_; + + /* + * The frame's paint ready QImage. + */ + std::unique_ptr image_; + + /* + * Used to protect the buffer during QImage creation routine. + */ + QMutex mutex_; + + /* + * True if the object is rendering + */ + std::atomic_bool isRendering_; + + /* + * Convenience ref to avmodel + */ + AVModel &avModel_; + + /* + * Connections to the underlying renderer signals in avmodel + */ + RenderConnections renderConnections_; +}; + +/** + * RenderManager filters signals and ecapsulates preview and distant + * frame wrappers, providing access to QImages for each and simplified + * start/stop mechanisms for renderers. It should contain as much + * renderer control logic as possible and prevent ui widgets from directly + * interfacing the rendering logic. + */ +class RenderManager final : public QObject +{ + Q_OBJECT; + +public: + explicit RenderManager(AVModel &avModel); + ~RenderManager(); + + /* + * Check if the preview is active. + */ + bool isPreviewing(); + /* + * Get the most recently rendered preview frame as a QImage. + * @return the rendered preview image + */ + QImage *getPreviewFrame(); + /* + * Start capturing and rendering preview frames. + * @param force if the capture device should be started + * @param async + */ + void startPreviewing(bool force = false, bool async = true); + /* + * Stop capturing. + * @param async + */ + void stopPreviewing(bool async = true); + + /* + * Get the most recently rendered distant frame for a given id + * as a QImage. + * @return the rendered preview image + */ + QImage *getFrame(const QString &id); + /* + * Add and connect a distant renderer for a given id + * to a FrameWrapper object + * @param id + */ + void addDistantRenderer(const QString &id); + /* + * Disconnect and remove a FrameWrapper object connected to a + * distant renderer for a given id + * @param id + */ + void removeDistantRenderer(const QString &id); + +signals: + /* + * Emitted when the size of the video capture device list changes. + */ + void videoDeviceListChanged(); + + /* + * Emitted when the preview is started. + */ + void previewRenderingStarted(); + + /* + * Emitted when the preview has a new frame ready. + */ + void previewFrameUpdated(); + + /* + * Emitted when the preview is stopped. + */ + void previewRenderingStopped(); + + /* + * Emitted when a distant renderer is started for a given id. + */ + void distantRenderingStarted(const QString &id); + + /* + * Emitted when a distant renderer has a new frame ready for a given id. + */ + void distantFrameUpdated(const QString &id); + + /* + * Emitted when a distant renderer is stopped for a given id. + */ + void distantRenderingStopped(const QString &id); + +private slots: + /* + * Used to listen to AVModel::deviceEvent. + */ + void slotDeviceEvent(); + +private: + /* + * Used to classify capture device events. + */ + enum class DeviceEvent { Added, RemovedCurrent, None }; + + /* + * Used to track the capture device count. + */ + int deviceListSize_; + + /* + * One preview frame. + */ + std::unique_ptr previewFrameWrapper_; + + /* + * Distant for each call/conf/conversation. + */ + std::map> distantFrameWrapperMap_; + std::map distantConnectionMap_; + + /* + * Convenience ref to avmodel. + */ + AVModel &avModel_; +}; +#if QT_VERSION >= QT_VERSION_CHECK(5, 8, 0) +Q_DECLARE_METATYPE(RenderManager *) +#endif diff --git a/src/runguard.cpp b/src/runguard.cpp new file mode 100644 index 00000000..4d22959d --- /dev/null +++ b/src/runguard.cpp @@ -0,0 +1,130 @@ +/* + * Copyright (C) 2019-2020 by Savoir-faire Linux + * Author: Andreas Traczyk + * + * 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 . + */ +// Based on: https://stackoverflow.com/a/28172162 + +#include "runguard.h" +#include + +namespace { + +QString +generateKeyHash(const QString &key, const QString &salt) +{ + QByteArray data; + + data.append(key.toUtf8()); + data.append(salt.toUtf8()); + data = QCryptographicHash::hash(data, QCryptographicHash::Sha1).toHex(); + + return data; +} + +} // namespace + +RunGuard::RunGuard(const QString &key) + : key_(key) + , memLockKey_(generateKeyHash(key, "_memLockKey")) + , sharedmemKey_(generateKeyHash(key, "_sharedmemKey")) + , sharedMem_(sharedmemKey_) + , memLock_(memLockKey_, 1) +{} + +RunGuard::~RunGuard() +{ + release(); +} + +void +RunGuard::tryRestorePrimaryInstance() +{ + /* + * TODO: relaunch application + */ +} + +bool +RunGuard::isAnotherRunning() +{ + if (sharedMem_.isAttached()) + return false; + + memLock_.acquire(); + const bool isRunning = sharedMem_.attach(); + if (isRunning) + sharedMem_.detach(); + memLock_.release(); + + return isRunning; +} + +bool +RunGuard::tryToRun() +{ +#ifdef Q_OS_WIN + if (isAnotherRunning()) { + /* + * This is a secondary instance, + * connect to the primary instance to trigger a restore + * then fail. + */ + if (socket_ == nullptr) { + socket_ = new QLocalSocket(); + } + if (socket_->state() == QLocalSocket::UnconnectedState + || socket_->state() == QLocalSocket::ClosingState) { + socket_->connectToServer(key_); + } + if (socket_->state() == QLocalSocket::ConnectingState) { + socket_->waitForConnected(); + } + return false; + } + + memLock_.acquire(); + const bool result = sharedMem_.create(sizeof(quint64)); + memLock_.release(); + if (!result) { + release(); + return false; + } + + /* + * This is the primary instance, + * listen for subsequent instances. + */ + QLocalServer::removeServer(key_); + server_ = new QLocalServer(); + server_->setSocketOptions(QLocalServer::UserAccessOption); + server_->listen(key_); + QObject::connect(server_, + &QLocalServer::newConnection, + this, + &RunGuard::tryRestorePrimaryInstance); +#endif + + return true; +} + +void +RunGuard::release() +{ + memLock_.acquire(); + if (sharedMem_.isAttached()) + sharedMem_.detach(); + memLock_.release(); +} \ No newline at end of file diff --git a/src/runguard.h b/src/runguard.h new file mode 100644 index 00000000..6e0f0d76 --- /dev/null +++ b/src/runguard.h @@ -0,0 +1,55 @@ +/* + * Copyright (C) 2019-2020 by Savoir-faire Linux + * Author: Andreas Traczyk + * + * 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 . + */ +// Based on: https://stackoverflow.com/a/28172162 + +#pragma once + +#include +#include +#include +#include +#include + +class RunGuard : public QObject +{ + Q_OBJECT; + +public: + RunGuard(const QString &key); + ~RunGuard(); + + bool isAnotherRunning(); + bool tryToRun(); + void release(); + +private slots: + void tryRestorePrimaryInstance(); + +private: + const QString key_; + const QString memLockKey_; + const QString sharedmemKey_; + + QSharedMemory sharedMem_; + QSystemSemaphore memLock_; + + QLocalSocket *socket_; + QLocalServer *server_; + + Q_DISABLE_COPY(RunGuard) +}; \ No newline at end of file diff --git a/src/settingsadaptor.cpp b/src/settingsadaptor.cpp new file mode 100644 index 00000000..471b25f5 --- /dev/null +++ b/src/settingsadaptor.cpp @@ -0,0 +1,1047 @@ +/* + * Copyright (C) 2020 by Savoir-faire Linux + * Author: Yang Wang + * + * 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 . + */ + +#include "settingsadaptor.h" + +#include "api/newdevicemodel.h" + +SettingsAdaptor::SettingsAdaptor(QObject *parent) + : QObject(parent) +{} + +///Singleton +SettingsAdaptor & +SettingsAdaptor::instance() +{ + static auto instance = new SettingsAdaptor; + return *instance; +} + +QString +SettingsAdaptor::getDir_Document() +{ + return QDir::toNativeSeparators( + QStandardPaths::writableLocation(QStandardPaths::DocumentsLocation)); +} + +QString +SettingsAdaptor::getDir_Download() +{ + QString downloadPath = QDir::toNativeSeparators(LRCInstance::dataTransferModel().downloadDirectory); + if (downloadPath.isEmpty()) { + downloadPath = lrc::api::DataTransferModel::createDefaultDirectory(); + setDownloadPath(downloadPath); + LRCInstance::dataTransferModel().downloadDirectory = downloadPath; + } +#ifdef Q_OS_WIN + int pos = downloadPath.lastIndexOf(QChar('\\')); +#else + int pos = downloadPath.lastIndexOf(QChar('/')); +#endif + if (pos == downloadPath.length() - 1) + downloadPath.truncate(pos); + return downloadPath; +} + +bool +SettingsAdaptor::getSettingsValue_CloseOrMinimized() +{ + QSettings settings("jami.net", "Jami"); + return settings.value(SettingsKey::closeOrMinimized).toBool(); +} + +bool +SettingsAdaptor::getSettingsValue_EnableNotifications() +{ + QSettings settings("jami.net", "Jami"); + return settings.value(SettingsKey::enableNotifications).toBool(); +} + +bool +SettingsAdaptor::getSettingsValue_AutoUpdate() +{ + QSettings settings("jami.net", "Jami"); + return settings.value(SettingsKey::autoUpdate).toBool(); +} + +void +SettingsAdaptor::setClosedOrMin(bool state) +{ + QSettings settings("jami.net", "Jami"); + settings.setValue(SettingsKey::closeOrMinimized, state); +} + +void +SettingsAdaptor::setNotifications(bool state) +{ + QSettings settings("jami.net", "Jami"); + settings.setValue(SettingsKey::enableNotifications, state); +} + +void +SettingsAdaptor::setUpdateAutomatic(bool state) +{ +#ifdef Q_OS_WIN + QSettings settings("jami.net", "Jami"); + settings.setValue(SettingsKey::autoUpdate, state); +#endif +} + +void +SettingsAdaptor::setRunOnStartUp(bool state) +{ + if (Utils::CheckStartupLink(L"Jami")) { + if (!state) { + Utils::DeleteStartupLink(L"Jami"); + } + } else if (state) { + Utils::CreateStartupLink(L"Jami"); + } +} + +void +SettingsAdaptor::setDownloadPath(QString dir) +{ + QSettings settings("jami.net", "Jami"); + settings.setValue(SettingsKey::downloadPath, dir); + LRCInstance::dataTransferModel().downloadDirectory = dir + "/"; +} + +lrc::api::video::ResRateList +SettingsAdaptor::get_ResRateList(lrc::api::video::Channel channel, QString device) +{ + auto deviceCapabilities = get_DeviceCapabilities(device); + + return deviceCapabilities[channel]; +} + +int +SettingsAdaptor::get_DeviceCapabilitiesSize(const QString &device) +{ + return get_DeviceCapabilities(device).size(); +} + +QVector +SettingsAdaptor::getResolutions(const QString &device) +{ + QVector resolutions; + + auto currentSettings = LRCInstance::avModel().getDeviceSettings(device); + + auto currentChannel = currentSettings.channel.isEmpty() ? "default" : currentSettings.channel; + auto channelCaps = get_ResRateList(currentChannel, device); + for (auto [resolution, frameRateList] : channelCaps) { + for (auto rate : frameRateList) { + resolutions.append(resolution); + } + } + + return resolutions; +} + +QVector +SettingsAdaptor::getFrameRates(const QString &device) +{ + QVector rates; + + auto currentSettings = LRCInstance::avModel().getDeviceSettings(device); + + auto currentChannel = currentSettings.channel.isEmpty() ? "default" : currentSettings.channel; + auto channelCaps = get_ResRateList(currentChannel, device); + for (auto [resolution, frameRateList] : channelCaps) { + for (auto rate : frameRateList) { + rates.append((int) rate); + } + } + + return rates; +} + +lrc::api::video::Capabilities +SettingsAdaptor::get_DeviceCapabilities(const QString &device) +{ + return LRCInstance::avModel().getDeviceCapabilities(device); +} + +QString +SettingsAdaptor::get_Video_Settings_Channel(const QString &deviceId) +{ + auto settings = LRCInstance::avModel().getDeviceSettings(deviceId); + + return (QString) settings.channel; +} + +QString +SettingsAdaptor::get_Video_Settings_Name(const QString &deviceId) +{ + auto settings = LRCInstance::avModel().getDeviceSettings(deviceId); + + return (QString) settings.name; +} + +QString +SettingsAdaptor::get_Video_Settings_Id(const QString &deviceId) +{ + auto settings = LRCInstance::avModel().getDeviceSettings(deviceId); + + return (QString) settings.id; +} + +qreal +SettingsAdaptor::get_Video_Settings_Rate(const QString &deviceId) +{ + auto settings = LRCInstance::avModel().getDeviceSettings(deviceId); + + return (qreal) settings.rate; +} + +QString +SettingsAdaptor::get_Video_Settings_Size(const QString &deviceId) +{ + auto settings = LRCInstance::avModel().getDeviceSettings(deviceId); + + return (QString) settings.size; +} + +void +SettingsAdaptor::set_Video_Settings_Rate_And_Resolution(const QString &deviceId, + qreal rate, + const QString &resolution) +{ + auto settings = LRCInstance::avModel().getDeviceSettings(deviceId); + settings.rate = rate; + settings.size = resolution; + LRCInstance::avModel().setDeviceSettings(settings); +} + +const lrc::api::account::Info & +SettingsAdaptor::getCurrentAccountInfo() +{ + return LRCInstance::getCurrentAccountInfo(); +} + +const Q_INVOKABLE lrc::api::profile::Info & +SettingsAdaptor::getCurrentAccount_Profile_Info() +{ + return LRCInstance::getCurrentAccountInfo().profileInfo; +} + +lrc::api::ContactModel * +SettingsAdaptor::getContactModel() +{ + return getCurrentAccountInfo().contactModel.get(); +} + +lrc::api::NewDeviceModel * +SettingsAdaptor::getDeviceModel() +{ + return getCurrentAccountInfo().deviceModel.get(); +} + +QString +SettingsAdaptor::get_CurrentAccountInfo_RegisteredName() +{ + return LRCInstance::getCurrentAccountInfo().registeredName; +} + +QString +SettingsAdaptor::get_CurrentAccountInfo_Id() +{ + return LRCInstance::getCurrentAccountInfo().id; +} + +bool +SettingsAdaptor::get_CurrentAccountInfo_Enabled() +{ + return LRCInstance::getCurrentAccountInfo().enabled; +} + +QString +SettingsAdaptor::getCurrentAccount_Profile_Info_Uri() +{ + return getCurrentAccount_Profile_Info().uri; +} + +QString +SettingsAdaptor::getCurrentAccount_Profile_Info_Alias() +{ + return getCurrentAccount_Profile_Info().alias; +} + +int +SettingsAdaptor::getCurrentAccount_Profile_Info_Type() +{ + return (int) (getCurrentAccount_Profile_Info().type); +} + +QString +SettingsAdaptor::getAccountBestName() +{ + return Utils::bestNameForAccount(LRCInstance::getCurrentAccountInfo()); +} + +QString +SettingsAdaptor::getAvatarImage_Base64(int avatarSize) +{ + auto &accountInfo = LRCInstance::getCurrentAccountInfo(); + auto avatar = Utils::accountPhoto(accountInfo, {avatarSize, avatarSize}); + + return QString::fromLatin1(Utils::QImageToByteArray(avatar).toBase64().data()); +} + +bool +SettingsAdaptor::getIsDefaultAvatar() +{ + auto &accountInfo = LRCInstance::getCurrentAccountInfo(); + + return accountInfo.profileInfo.avatar.isEmpty(); +} + +bool +SettingsAdaptor::setCurrAccAvatar(QString avatarImgBase64) +{ + QImage avatarImg; + const bool ret = avatarImg.loadFromData(QByteArray::fromBase64(avatarImgBase64.toLatin1())); + if (!ret) { + qDebug() << "Current avatar loading from base64 fail"; + return false; + } else { + LRCInstance::setCurrAccAvatar(QPixmap::fromImage(avatarImg)); + } + return true; +} + +void +SettingsAdaptor::clearCurrentAvatar() +{ + LRCInstance::setCurrAccAvatar(QPixmap()); +} + +lrc::api::account::ConfProperties_t +SettingsAdaptor::getAccountConfig() +{ + return LRCInstance::accountModel().getAccountConfig(LRCInstance::getCurrAccId()); +} + +QString +SettingsAdaptor::getAccountConfig_Manageruri() +{ + return getAccountConfig().managerUri; +} + +QString +SettingsAdaptor::getAccountConfig_Username() +{ + return getAccountConfig().username; +} + +QString +SettingsAdaptor::getAccountConfig_Hostname() +{ + return getAccountConfig().hostname; +} + +QString +SettingsAdaptor::getAccountConfig_Password() +{ + return getAccountConfig().password; +} + +QString +SettingsAdaptor::getAccountConfig_ProxyServer() +{ + return getAccountConfig().proxyServer; +} + +bool +SettingsAdaptor::getAccountConfig_PeerDiscovery() +{ + return getAccountConfig().peerDiscovery; +} + +bool +SettingsAdaptor::getAccountConfig_DHT_PublicInCalls() +{ + return getAccountConfig().DHT.PublicInCalls; +} + +bool +SettingsAdaptor::getAccountConfig_AutoAnswer() +{ + return getAccountConfig().autoAnswer; +} + +QString +SettingsAdaptor::getAccountConfig_RingNS_Uri() +{ + return getAccountConfig().RingNS.uri; +} + +bool +SettingsAdaptor::getAccountConfig_ProxyEnabled() +{ + return getAccountConfig().proxyEnabled; +} + +QString +SettingsAdaptor::getAccountConfig_TLS_CertificateListFile() +{ + return getAccountConfig().TLS.certificateListFile; +} + +QString +SettingsAdaptor::getAccountConfig_TLS_CertificateFile() +{ + return getAccountConfig().TLS.certificateFile; +} + +QString +SettingsAdaptor::getAccountConfig_TLS_PrivateKeyFile() +{ + return getAccountConfig().TLS.privateKeyFile; +} + +bool +SettingsAdaptor::getAccountConfig_TLS_Enable() +{ + return getAccountConfig().TLS.enable; +} + +QString +SettingsAdaptor::getAccountConfig_TLS_Password() +{ + return getAccountConfig().TLS.password; +} + +bool +SettingsAdaptor::getAccountConfig_TLS_VerifyServer() +{ + return getAccountConfig().TLS.verifyServer; +} + +bool +SettingsAdaptor::getAccountConfig_TLS_VerifyClient() +{ + return getAccountConfig().TLS.verifyClient; +} + +bool +SettingsAdaptor::getAccountConfig_TLS_RequireClientCertificate() +{ + return getAccountConfig().TLS.requireClientCertificate; +} + +int +SettingsAdaptor::getAccountConfig_TLS_Method_inInt() +{ + return (int) getAccountConfig().TLS.method; +} + +QString +SettingsAdaptor::getAccountConfig_TLS_Servername() +{ + return getAccountConfig().TLS.serverName; +} + +int +SettingsAdaptor::getAccountConfig_TLS_NegotiationTimeoutSec() +{ + return getAccountConfig().TLS.negotiationTimeoutSec; +} + +bool +SettingsAdaptor::getAccountConfig_SRTP_Enabled() +{ + return getAccountConfig().SRTP.enable; +} + +int +SettingsAdaptor::getAccountConfig_SRTP_KeyExchange() +{ + return (int) getAccountConfig().SRTP.keyExchange; +} + +bool +SettingsAdaptor::getAccountConfig_SRTP_RtpFallback() +{ + return getAccountConfig().SRTP.rtpFallback; +} + +bool +SettingsAdaptor::getAccountConfig_UpnpEnabled() +{ + return getAccountConfig().upnpEnabled; +} + +bool +SettingsAdaptor::getAccountConfig_TURN_Enabled() +{ + return getAccountConfig().TURN.enable; +} + +QString +SettingsAdaptor::getAccountConfig_TURN_Server() +{ + return getAccountConfig().TURN.server; +} + +QString +SettingsAdaptor::getAccountConfig_TURN_Username() +{ + return getAccountConfig().TURN.username; +} + +QString +SettingsAdaptor::getAccountConfig_TURN_Password() +{ + return getAccountConfig().TURN.password; +} + +QString +SettingsAdaptor::getAccountConfig_TURN_Realm() +{ + return getAccountConfig().TURN.realm; +} + +bool +SettingsAdaptor::getAccountConfig_STUN_Enabled() +{ + return getAccountConfig().STUN.enable; +} + +QString +SettingsAdaptor::getAccountConfig_STUN_Server() +{ + return getAccountConfig().STUN.server; +} + +bool +SettingsAdaptor::getAccountConfig_Video_Enabled() +{ + return getAccountConfig().Video.videoEnabled; +} + +int +SettingsAdaptor::getAccountConfig_Video_VideoPortMin() +{ + return getAccountConfig().Video.videoPortMin; +} + +int +SettingsAdaptor::getAccountConfig_Video_VideoPortMax() +{ + return getAccountConfig().Video.videoPortMax; +} + +int +SettingsAdaptor::getAccountConfig_Audio_AudioPortMin() +{ + return getAccountConfig().Audio.audioPortMin; +} + +int +SettingsAdaptor::getAccountConfig_Audio_AudioPortMax() +{ + return getAccountConfig().Audio.audioPortMax; +} + +bool +SettingsAdaptor::getAccountConfig_Ringtone_RingtoneEnabled() +{ + return getAccountConfig().Ringtone.ringtoneEnabled; +} + +QString +SettingsAdaptor::getAccountConfig_Ringtone_RingtonePath() +{ + return getAccountConfig().Ringtone.ringtonePath; +} + +int +SettingsAdaptor::getAccountConfig_Registration_Expire() +{ + return getAccountConfig().Registration.expire; +} + +int +SettingsAdaptor::getAccountConfig_Localport() +{ + return getAccountConfig().localPort; +} + +bool +SettingsAdaptor::getAccountConfig_PublishedSameAsLocal() +{ + return getAccountConfig().publishedSameAsLocal; +} + +QString +SettingsAdaptor::getAccountConfig_PublishedAddress() +{ + return getAccountConfig().publishedAddress; +} + +int +SettingsAdaptor::getAccountConfig_PublishedPort() +{ + return getAccountConfig().publishedPort; +} + +QString +SettingsAdaptor::getAccountConfig_Mailbox() +{ + return getAccountConfig().mailbox; +} + +void +SettingsAdaptor::setAccountConfig_Username(QString input) +{ + auto confProps = getAccountConfig(); + confProps.username = input; + LRCInstance::accountModel().setAccountConfig(LRCInstance::getCurrAccId(), confProps); +} + +void +SettingsAdaptor::setAccountConfig_Hostname(QString input) +{ + auto confProps = getAccountConfig(); + confProps.hostname = input; + LRCInstance::accountModel().setAccountConfig(LRCInstance::getCurrAccId(), confProps); +} + +void +SettingsAdaptor::setAccountConfig_Password(QString input) +{ + auto confProps = getAccountConfig(); + confProps.password = input; + LRCInstance::accountModel().setAccountConfig(LRCInstance::getCurrAccId(), confProps); +} + +void +SettingsAdaptor::setAccountConfig_ProxyServer(QString input) +{ + auto confProps = getAccountConfig(); + confProps.proxyServer = input; + LRCInstance::accountModel().setAccountConfig(LRCInstance::getCurrAccId(), confProps); +} + +void +SettingsAdaptor::setAutoConnectOnLocalNetwork(bool state) +{ + auto confProps = LRCInstance::accountModel().getAccountConfig(LRCInstance::getCurrAccId()); + confProps.peerDiscovery = state; + LRCInstance::accountModel().setAccountConfig(LRCInstance::getCurrAccId(), confProps); +} + +void +SettingsAdaptor::setCallsUntrusted(bool state) +{ + auto confProps = LRCInstance::accountModel().getAccountConfig(LRCInstance::getCurrAccId()); + confProps.DHT.PublicInCalls = state; + LRCInstance::accountModel().setAccountConfig(LRCInstance::getCurrAccId(), confProps); +} + +void +SettingsAdaptor::setAutoAnswerCalls(bool state) +{ + auto confProps = LRCInstance::accountModel().getAccountConfig(LRCInstance::getCurrAccId()); + confProps.autoAnswer = state; + LRCInstance::accountModel().setAccountConfig(LRCInstance::getCurrAccId(), confProps); +} + +void +SettingsAdaptor::setEnableRingtone(bool state) +{ + auto confProps = LRCInstance::accountModel().getAccountConfig(LRCInstance::getCurrAccId()); + confProps.Ringtone.ringtoneEnabled = state; + LRCInstance::accountModel().setAccountConfig(LRCInstance::getCurrAccId(), confProps); +} + +void +SettingsAdaptor::setEnableProxy(bool state) +{ + auto confProps = LRCInstance::accountModel().getAccountConfig(LRCInstance::getCurrAccId()); + confProps.proxyEnabled = state; + LRCInstance::accountModel().setAccountConfig(LRCInstance::getCurrAccId(), confProps); +} + +void +SettingsAdaptor::setUseUPnP(bool state) +{ + auto confProps = LRCInstance::accountModel().getAccountConfig(LRCInstance::getCurrAccId()); + confProps.upnpEnabled = state; + LRCInstance::accountModel().setAccountConfig(LRCInstance::getCurrAccId(), confProps); +} + +void +SettingsAdaptor::setUseTURN(bool state) +{ + auto confProps = LRCInstance::accountModel().getAccountConfig(LRCInstance::getCurrAccId()); + confProps.TURN.enable = state; + LRCInstance::accountModel().setAccountConfig(LRCInstance::getCurrAccId(), confProps); +} + +void +SettingsAdaptor::setUseSTUN(bool state) +{ + auto confProps = LRCInstance::accountModel().getAccountConfig(LRCInstance::getCurrAccId()); + confProps.STUN.enable = state; + LRCInstance::accountModel().setAccountConfig(LRCInstance::getCurrAccId(), confProps); +} + +void +SettingsAdaptor::setVideoState(bool state) +{ + auto confProps = LRCInstance::accountModel().getAccountConfig(LRCInstance::getCurrAccId()); + confProps.Video.videoEnabled = state; + LRCInstance::accountModel().setAccountConfig(LRCInstance::getCurrAccId(), confProps); +} + +void +SettingsAdaptor::setUseSRTP(bool state) +{ + auto confProps = LRCInstance::accountModel().getAccountConfig(LRCInstance::getCurrAccId()); + confProps.SRTP.enable = state; + LRCInstance::accountModel().setAccountConfig(LRCInstance::getCurrAccId(), confProps); +} + +void +SettingsAdaptor::setUseSDES(bool state) +{ + auto confProps = LRCInstance::accountModel().getAccountConfig(LRCInstance::getCurrAccId()); + confProps.SRTP.keyExchange = state ? lrc::api::account::KeyExchangeProtocol::SDES + : lrc::api::account::KeyExchangeProtocol::NONE; + LRCInstance::accountModel().setAccountConfig(LRCInstance::getCurrAccId(), confProps); +} + +void +SettingsAdaptor::setUseRTPFallback(bool state) +{ + auto confProps = LRCInstance::accountModel().getAccountConfig(LRCInstance::getCurrAccId()); + confProps.SRTP.rtpFallback = state; + LRCInstance::accountModel().setAccountConfig(LRCInstance::getCurrAccId(), confProps); +} + +void +SettingsAdaptor::setUseTLS(bool state) +{ + auto confProps = LRCInstance::accountModel().getAccountConfig(LRCInstance::getCurrAccId()); + confProps.TLS.enable = state; + LRCInstance::accountModel().setAccountConfig(LRCInstance::getCurrAccId(), confProps); +} + +void +SettingsAdaptor::setVerifyCertificatesServer(bool state) +{ + auto confProps = LRCInstance::accountModel().getAccountConfig(LRCInstance::getCurrAccId()); + confProps.TLS.verifyServer = state; + LRCInstance::accountModel().setAccountConfig(LRCInstance::getCurrAccId(), confProps); +} + +void +SettingsAdaptor::setVerifyCertificatesClient(bool state) +{ + auto confProps = LRCInstance::accountModel().getAccountConfig(LRCInstance::getCurrAccId()); + confProps.TLS.verifyClient = state; + LRCInstance::accountModel().setAccountConfig(LRCInstance::getCurrAccId(), confProps); +} + +void +SettingsAdaptor::setRequireCertificatesIncomingTLS(bool state) +{ + auto confProps = LRCInstance::accountModel().getAccountConfig(LRCInstance::getCurrAccId()); + confProps.TLS.requireClientCertificate = state; + LRCInstance::accountModel().setAccountConfig(LRCInstance::getCurrAccId(), confProps); +} + +void +SettingsAdaptor::setUseCustomAddressAndPort(bool state) +{ + auto confProps = LRCInstance::accountModel().getAccountConfig(LRCInstance::getCurrAccId()); + confProps.publishedSameAsLocal = state; + LRCInstance::accountModel().setAccountConfig(LRCInstance::getCurrAccId(), confProps); +} + +void +SettingsAdaptor::setNameServer(QString text) +{ + auto confProps = LRCInstance::accountModel().getAccountConfig(LRCInstance::getCurrAccId()); + confProps.RingNS.uri = text; + LRCInstance::accountModel().setAccountConfig(LRCInstance::getCurrAccId(), confProps); +} + +void +SettingsAdaptor::setProxyAddress(QString text) +{ + auto confProps = LRCInstance::accountModel().getAccountConfig(LRCInstance::getCurrAccId()); + confProps.proxyServer = text; + LRCInstance::accountModel().setAccountConfig(LRCInstance::getCurrAccId(), confProps); +} + +void +SettingsAdaptor::setBootstrapAddress(QString text) +{ + auto confProps = LRCInstance::accountModel().getAccountConfig(LRCInstance::getCurrAccId()); + confProps.hostname = text; + LRCInstance::accountModel().setAccountConfig(LRCInstance::getCurrAccId(), confProps); +} + +void +SettingsAdaptor::setTURNAddress(QString text) +{ + auto confProps = LRCInstance::accountModel().getAccountConfig(LRCInstance::getCurrAccId()); + confProps.TURN.server = text; + LRCInstance::accountModel().setAccountConfig(LRCInstance::getCurrAccId(), confProps); +} + +void +SettingsAdaptor::setTURNUsername(QString text) +{ + auto confProps = LRCInstance::accountModel().getAccountConfig(LRCInstance::getCurrAccId()); + confProps.TURN.username = text; + LRCInstance::accountModel().setAccountConfig(LRCInstance::getCurrAccId(), confProps); +} + +void +SettingsAdaptor::setTURNPassword(QString text) +{ + auto confProps = LRCInstance::accountModel().getAccountConfig(LRCInstance::getCurrAccId()); + confProps.TURN.password = text; + LRCInstance::accountModel().setAccountConfig(LRCInstance::getCurrAccId(), confProps); +} + +void +SettingsAdaptor::setTURNRealm(QString text) +{ + auto confProps = LRCInstance::accountModel().getAccountConfig(LRCInstance::getCurrAccId()); + confProps.TURN.realm = text; + LRCInstance::accountModel().setAccountConfig(LRCInstance::getCurrAccId(), confProps); +} + +void +SettingsAdaptor::setSTUNAddress(QString text) +{ + auto confProps = LRCInstance::accountModel().getAccountConfig(LRCInstance::getCurrAccId()); + confProps.STUN.server = text; + LRCInstance::accountModel().setAccountConfig(LRCInstance::getCurrAccId(), confProps); +} + +void +SettingsAdaptor::lineEditVoiceMailDialCodeEditFinished(QString text) +{ + auto confProps = LRCInstance::accountModel().getAccountConfig(LRCInstance::getCurrAccId()); + confProps.mailbox = text; + LRCInstance::accountModel().setAccountConfig(LRCInstance::getCurrAccId(), confProps); +} + +void +SettingsAdaptor::outgoingTLSServerNameLineEditTextChanged(QString text) +{ + auto confProps = LRCInstance::accountModel().getAccountConfig(LRCInstance::getCurrAccId()); + confProps.TLS.serverName = text; + LRCInstance::accountModel().setAccountConfig(LRCInstance::getCurrAccId(), confProps); +} + +void +SettingsAdaptor::lineEditSIPCertPasswordLineEditTextChanged(QString text) +{ + auto confProps = LRCInstance::accountModel().getAccountConfig(LRCInstance::getCurrAccId()); + confProps.TLS.password = text; + LRCInstance::accountModel().setAccountConfig(LRCInstance::getCurrAccId(), confProps); +} + +void +SettingsAdaptor::lineEditSIPCustomAddressLineEditTextChanged(QString text) +{ + auto confProps = LRCInstance::accountModel().getAccountConfig(LRCInstance::getCurrAccId()); + confProps.publishedAddress = text; + LRCInstance::accountModel().setAccountConfig(LRCInstance::getCurrAccId(), confProps); +} + +void +SettingsAdaptor::customPortSIPSpinBoxValueChanged(int value) +{ + auto confProps = LRCInstance::accountModel().getAccountConfig(LRCInstance::getCurrAccId()); + confProps.publishedPort = value; + LRCInstance::accountModel().setAccountConfig(LRCInstance::getCurrAccId(), confProps); +} + +void +SettingsAdaptor::negotiationTimeoutSpinBoxValueChanged(int value) +{ + auto confProps = LRCInstance::accountModel().getAccountConfig(LRCInstance::getCurrAccId()); + confProps.TLS.negotiationTimeoutSec = value; + LRCInstance::accountModel().setAccountConfig(LRCInstance::getCurrAccId(), confProps); +} + +void +SettingsAdaptor::registrationTimeoutSpinBoxValueChanged(int value) +{ + auto confProps = LRCInstance::accountModel().getAccountConfig(LRCInstance::getCurrAccId()); + confProps.Registration.expire = value; + LRCInstance::accountModel().setAccountConfig(LRCInstance::getCurrAccId(), confProps); +} + +void +SettingsAdaptor::networkInterfaceSpinBoxValueChanged(int value) +{ + auto confProps = LRCInstance::accountModel().getAccountConfig(LRCInstance::getCurrAccId()); + confProps.localPort = value; + LRCInstance::accountModel().setAccountConfig(LRCInstance::getCurrAccId(), confProps); +} + +void +SettingsAdaptor::audioRTPMinPortSpinBoxEditFinished(int value) +{ + auto confProps = LRCInstance::accountModel().getAccountConfig(LRCInstance::getCurrAccId()); + confProps.Audio.audioPortMin = value; + LRCInstance::accountModel().setAccountConfig(LRCInstance::getCurrAccId(), confProps); +} + +void +SettingsAdaptor::audioRTPMaxPortSpinBoxEditFinished(int value) +{ + auto confProps = LRCInstance::accountModel().getAccountConfig(LRCInstance::getCurrAccId()); + confProps.Audio.audioPortMax = value; + LRCInstance::accountModel().setAccountConfig(LRCInstance::getCurrAccId(), confProps); +} + +void +SettingsAdaptor::videoRTPMinPortSpinBoxEditFinished(int value) +{ + auto confProps = LRCInstance::accountModel().getAccountConfig(LRCInstance::getCurrAccId()); + confProps.Video.videoPortMin = value; + LRCInstance::accountModel().setAccountConfig(LRCInstance::getCurrAccId(), confProps); +} + +void +SettingsAdaptor::videoRTPMaxPortSpinBoxEditFinished(int value) +{ + auto confProps = LRCInstance::accountModel().getAccountConfig(LRCInstance::getCurrAccId()); + confProps.Video.videoPortMax = value; + LRCInstance::accountModel().setAccountConfig(LRCInstance::getCurrAccId(), confProps); +} + +void +SettingsAdaptor::tlsProtocolComboBoxIndexChanged(const int &index) +{ + auto confProps = LRCInstance::accountModel().getAccountConfig(LRCInstance::getCurrAccId()); + + if (static_cast(confProps.TLS.method) != index) { + if (index == 0) { + confProps.TLS.method = lrc::api::account::TlsMethod::DEFAULT; + } else if (index == 1) { + confProps.TLS.method = lrc::api::account::TlsMethod::TLSv1; + } else if (index == 2) { + confProps.TLS.method = lrc::api::account::TlsMethod::TLSv1_1; + } else { + confProps.TLS.method = lrc::api::account::TlsMethod::TLSv1_2; + } + LRCInstance::accountModel().setAccountConfig(LRCInstance::getCurrAccId(), confProps); + } +} + +void +SettingsAdaptor::setDeviceName(QString text) +{ + auto confProps = LRCInstance::accountModel().getAccountConfig(LRCInstance::getCurrAccId()); + confProps.deviceName = text; + LRCInstance::accountModel().setAccountConfig(LRCInstance::getCurrAccId(), confProps); +} + +void +SettingsAdaptor::unbanContact(int index) +{ + auto bannedContactList = LRCInstance::getCurrentAccountInfo().contactModel->getBannedContacts(); + auto it = bannedContactList.begin(); + std::advance(it, index); + + auto contactInfo = LRCInstance::getCurrentAccountInfo().contactModel->getContact(*it); + + LRCInstance::getCurrentAccountInfo().contactModel->addContact(contactInfo); +} + +void +SettingsAdaptor::audioCodecsStateChange(unsigned int id, bool isToEnable) +{ + auto audioCodecList = LRCInstance::getCurrentAccountInfo().codecModel->getAudioCodecs(); + LRCInstance::getCurrentAccountInfo().codecModel->enable(id, isToEnable); +} + +void +SettingsAdaptor::videoCodecsStateChange(unsigned int id, bool isToEnable) +{ + auto videoCodecList = LRCInstance::getCurrentAccountInfo().codecModel->getVideoCodecs(); + LRCInstance::getCurrentAccountInfo().codecModel->enable(id, isToEnable); +} + +void +SettingsAdaptor::decreaseAudioCodecPriority(unsigned int id) +{ + LRCInstance::getCurrentAccountInfo().codecModel->decreasePriority(id, false); +} + +void +SettingsAdaptor::increaseAudioCodecPriority(unsigned int id) +{ + LRCInstance::getCurrentAccountInfo().codecModel->increasePriority(id, false); +} + +void +SettingsAdaptor::decreaseVideoCodecPriority(unsigned int id) +{ + LRCInstance::getCurrentAccountInfo().codecModel->decreasePriority(id, true); +} + +void +SettingsAdaptor::increaseVideoCodecPriority(unsigned int id) +{ + LRCInstance::getCurrentAccountInfo().codecModel->increasePriority(id, true); +} + +void +SettingsAdaptor::set_RingtonePath(QString text) +{ + auto confProps = LRCInstance::accountModel().getAccountConfig(LRCInstance::getCurrAccId()); + confProps.Ringtone.ringtonePath = text; + LRCInstance::accountModel().setAccountConfig(LRCInstance::getCurrAccId(), confProps); +} + +void +SettingsAdaptor::set_FileCACert(QString text) +{ + auto confProps = LRCInstance::accountModel().getAccountConfig(LRCInstance::getCurrAccId()); + confProps.TLS.certificateListFile = text; + LRCInstance::accountModel().setAccountConfig(LRCInstance::getCurrAccId(), confProps); +} + +void +SettingsAdaptor::set_FileUserCert(QString text) +{ + auto confProps = LRCInstance::accountModel().getAccountConfig(LRCInstance::getCurrAccId()); + confProps.TLS.certificateFile = text; + LRCInstance::accountModel().setAccountConfig(LRCInstance::getCurrAccId(), confProps); +} + +void +SettingsAdaptor::set_FilePrivateKey(QString text) +{ + auto confProps = LRCInstance::accountModel().getAccountConfig(LRCInstance::getCurrAccId()); + confProps.TLS.privateKeyFile = text; + LRCInstance::accountModel().setAccountConfig(LRCInstance::getCurrAccId(), confProps); +} diff --git a/src/settingsadaptor.h b/src/settingsadaptor.h new file mode 100644 index 00000000..eec7784d --- /dev/null +++ b/src/settingsadaptor.h @@ -0,0 +1,241 @@ +/* + * Copyright (C) 2020 by Savoir-faire Linux + * Author: Yang Wang + * + * 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 . + */ + +#pragma once + +#include +#include + +#include "api/account.h" +#include "api/datatransfermodel.h" +#include "lrcinstance.h" +#include "typedefs.h" +#include "utils.h" + +class SettingsAdaptor : public QObject +{ + Q_OBJECT +public: + explicit SettingsAdaptor(QObject *parent = nullptr); + + //Singleton + static SettingsAdaptor &instance(); + /* + * getters of directories + */ + Q_INVOKABLE QString getDir_Document(); + Q_INVOKABLE QString getDir_Download(); + + /* + * getters and setters of app settings options + */ + Q_INVOKABLE bool getSettingsValue_CloseOrMinimized(); + Q_INVOKABLE bool getSettingsValue_EnableNotifications(); + Q_INVOKABLE bool getSettingsValue_AutoUpdate(); + + Q_INVOKABLE void setClosedOrMin(bool state); + Q_INVOKABLE void setNotifications(bool state); + Q_INVOKABLE void setUpdateAutomatic(bool state); + Q_INVOKABLE void setRunOnStartUp(bool state); + Q_INVOKABLE void setDownloadPath(QString dir); + + /* + * getters of devices' Info and options + */ + Q_INVOKABLE lrc::api::video::Capabilities get_DeviceCapabilities(const QString &device); + Q_INVOKABLE lrc::api::video::ResRateList get_ResRateList(lrc::api::video::Channel channel, + QString device); + Q_INVOKABLE int get_DeviceCapabilitiesSize(const QString &device); + + /* + * getters of resolution and frame rates of current device + */ + Q_INVOKABLE QVector getResolutions(const QString &device); + Q_INVOKABLE QVector getFrameRates(const QString &device); + + /* + * getters and setters: lrc video::setting + */ + Q_INVOKABLE QString get_Video_Settings_Channel(const QString &deviceId); + Q_INVOKABLE QString get_Video_Settings_Name(const QString &deviceId); + Q_INVOKABLE QString get_Video_Settings_Id(const QString &deviceId); + Q_INVOKABLE qreal get_Video_Settings_Rate(const QString &deviceId); + Q_INVOKABLE QString get_Video_Settings_Size(const QString &deviceId); + + Q_INVOKABLE void set_Video_Settings_Rate_And_Resolution(const QString &deviceId, + qreal rate, + const QString &resolution); + + /* + * getters and setters of current account Info + */ + const Q_INVOKABLE lrc::api::account::Info &getCurrentAccountInfo(); + const Q_INVOKABLE lrc::api::profile::Info &getCurrentAccount_Profile_Info(); + + Q_INVOKABLE lrc::api::ContactModel *getContactModel(); + Q_INVOKABLE lrc::api::NewDeviceModel *getDeviceModel(); + + Q_INVOKABLE QString get_CurrentAccountInfo_RegisteredName(); + Q_INVOKABLE QString get_CurrentAccountInfo_Id(); + Q_INVOKABLE bool get_CurrentAccountInfo_Enabled(); + + // profile info + Q_INVOKABLE QString getCurrentAccount_Profile_Info_Uri(); + Q_INVOKABLE QString getCurrentAccount_Profile_Info_Alias(); + Q_INVOKABLE int getCurrentAccount_Profile_Info_Type(); + Q_INVOKABLE QString getAccountBestName(); + + // getters and setters of avatar image + Q_INVOKABLE QString getAvatarImage_Base64(int avatarSize); + Q_INVOKABLE bool getIsDefaultAvatar(); + Q_INVOKABLE bool setCurrAccAvatar(QString avatarImgBase64); + Q_INVOKABLE void clearCurrentAvatar(); + + /* + * getters and setters of ConfProperties_t + */ + // getters + Q_INVOKABLE lrc::api::account::ConfProperties_t getAccountConfig(); + Q_INVOKABLE QString getAccountConfig_Manageruri(); + Q_INVOKABLE QString getAccountConfig_Username(); + Q_INVOKABLE QString getAccountConfig_Hostname(); + Q_INVOKABLE QString getAccountConfig_Password(); + + Q_INVOKABLE QString getAccountConfig_ProxyServer(); + Q_INVOKABLE bool getAccountConfig_ProxyEnabled(); + + Q_INVOKABLE bool getAccountConfig_PeerDiscovery(); + Q_INVOKABLE bool getAccountConfig_DHT_PublicInCalls(); + Q_INVOKABLE bool getAccountConfig_AutoAnswer(); + + Q_INVOKABLE QString getAccountConfig_RingNS_Uri(); + + Q_INVOKABLE QString getAccountConfig_TLS_CertificateListFile(); + Q_INVOKABLE QString getAccountConfig_TLS_CertificateFile(); + Q_INVOKABLE QString getAccountConfig_TLS_PrivateKeyFile(); + Q_INVOKABLE bool getAccountConfig_TLS_Enable(); + Q_INVOKABLE QString getAccountConfig_TLS_Password(); + Q_INVOKABLE bool getAccountConfig_TLS_VerifyServer(); + Q_INVOKABLE bool getAccountConfig_TLS_VerifyClient(); + Q_INVOKABLE bool getAccountConfig_TLS_RequireClientCertificate(); + Q_INVOKABLE int getAccountConfig_TLS_Method_inInt(); + Q_INVOKABLE QString getAccountConfig_TLS_Servername(); + Q_INVOKABLE int getAccountConfig_TLS_NegotiationTimeoutSec(); + + Q_INVOKABLE bool getAccountConfig_SRTP_Enabled(); + Q_INVOKABLE int getAccountConfig_SRTP_KeyExchange(); + Q_INVOKABLE bool getAccountConfig_SRTP_RtpFallback(); + + Q_INVOKABLE bool getAccountConfig_UpnpEnabled(); + Q_INVOKABLE bool getAccountConfig_TURN_Enabled(); + Q_INVOKABLE QString getAccountConfig_TURN_Server(); + Q_INVOKABLE QString getAccountConfig_TURN_Username(); + Q_INVOKABLE QString getAccountConfig_TURN_Password(); + Q_INVOKABLE QString getAccountConfig_TURN_Realm(); + + Q_INVOKABLE bool getAccountConfig_STUN_Enabled(); + Q_INVOKABLE QString getAccountConfig_STUN_Server(); + + Q_INVOKABLE bool getAccountConfig_Video_Enabled(); + Q_INVOKABLE int getAccountConfig_Video_VideoPortMin(); + Q_INVOKABLE int getAccountConfig_Video_VideoPortMax(); + + Q_INVOKABLE int getAccountConfig_Audio_AudioPortMin(); + Q_INVOKABLE int getAccountConfig_Audio_AudioPortMax(); + + Q_INVOKABLE bool getAccountConfig_Ringtone_RingtoneEnabled(); + Q_INVOKABLE QString getAccountConfig_Ringtone_RingtonePath(); + + Q_INVOKABLE int getAccountConfig_Registration_Expire(); + Q_INVOKABLE int getAccountConfig_Localport(); + Q_INVOKABLE bool getAccountConfig_PublishedSameAsLocal(); + Q_INVOKABLE QString getAccountConfig_PublishedAddress(); + Q_INVOKABLE int getAccountConfig_PublishedPort(); + + Q_INVOKABLE QString getAccountConfig_Mailbox(); + + // setters + Q_INVOKABLE void setAccountConfig_Username(QString input); + Q_INVOKABLE void setAccountConfig_Hostname(QString input); + Q_INVOKABLE void setAccountConfig_Password(QString input); + Q_INVOKABLE void setAccountConfig_ProxyServer(QString input); + + Q_INVOKABLE void setAutoConnectOnLocalNetwork(bool state); + Q_INVOKABLE void setCallsUntrusted(bool state); + Q_INVOKABLE void setAutoAnswerCalls(bool state); + Q_INVOKABLE void setEnableRingtone(bool state); + Q_INVOKABLE void setEnableProxy(bool state); + Q_INVOKABLE void setUseUPnP(bool state); + Q_INVOKABLE void setUseTURN(bool state); + Q_INVOKABLE void setUseSTUN(bool state); + Q_INVOKABLE void setVideoState(bool state); + Q_INVOKABLE void setUseSRTP(bool state); + Q_INVOKABLE void setUseSDES(bool state); + Q_INVOKABLE void setUseRTPFallback(bool state); + Q_INVOKABLE void setUseTLS(bool state); + Q_INVOKABLE void setVerifyCertificatesServer(bool state); + Q_INVOKABLE void setVerifyCertificatesClient(bool state); + Q_INVOKABLE void setRequireCertificatesIncomingTLS(bool state); + Q_INVOKABLE void setUseCustomAddressAndPort(bool state); + + Q_INVOKABLE void setNameServer(QString text); + Q_INVOKABLE void setProxyAddress(QString text); + Q_INVOKABLE void setBootstrapAddress(QString text); + Q_INVOKABLE void setTURNAddress(QString text); + Q_INVOKABLE void setTURNUsername(QString text); + Q_INVOKABLE void setTURNPassword(QString text); + Q_INVOKABLE void setTURNRealm(QString text); + Q_INVOKABLE void setSTUNAddress(QString text); + + Q_INVOKABLE void lineEditVoiceMailDialCodeEditFinished(QString text); + Q_INVOKABLE void outgoingTLSServerNameLineEditTextChanged(QString text); + Q_INVOKABLE void lineEditSIPCertPasswordLineEditTextChanged(QString text); + Q_INVOKABLE void lineEditSIPCustomAddressLineEditTextChanged(QString text); + + Q_INVOKABLE void customPortSIPSpinBoxValueChanged(int value); + Q_INVOKABLE void negotiationTimeoutSpinBoxValueChanged(int value); + Q_INVOKABLE void registrationTimeoutSpinBoxValueChanged(int value); + Q_INVOKABLE void networkInterfaceSpinBoxValueChanged(int value); + Q_INVOKABLE void audioRTPMinPortSpinBoxEditFinished(int value); + Q_INVOKABLE void audioRTPMaxPortSpinBoxEditFinished(int value); + Q_INVOKABLE void videoRTPMinPortSpinBoxEditFinished(int value); + Q_INVOKABLE void videoRTPMaxPortSpinBoxEditFinished(int value); + + Q_INVOKABLE void tlsProtocolComboBoxIndexChanged(const int &index); + + Q_INVOKABLE void setDeviceName(QString text); + + Q_INVOKABLE void unbanContact(int index); + + Q_INVOKABLE void audioCodecsStateChange(unsigned int id, bool isToEnable); + Q_INVOKABLE void videoCodecsStateChange(unsigned int id, bool isToEnable); + + Q_INVOKABLE void decreaseAudioCodecPriority(unsigned int id); + Q_INVOKABLE void increaseAudioCodecPriority(unsigned int id); + + Q_INVOKABLE void decreaseVideoCodecPriority(unsigned int id); + Q_INVOKABLE void increaseVideoCodecPriority(unsigned int id); + + Q_INVOKABLE void set_RingtonePath(QString text); + Q_INVOKABLE void set_FileCACert(QString text); + Q_INVOKABLE void set_FileUserCert(QString text); + Q_INVOKABLE void set_FilePrivateKey(QString text); +}; +#if QT_VERSION >= QT_VERSION_CHECK(5, 8, 0) +Q_DECLARE_METATYPE(SettingsAdaptor *) +#endif diff --git a/src/settingskey.h b/src/settingskey.h new file mode 100644 index 00000000..6c82598f --- /dev/null +++ b/src/settingskey.h @@ -0,0 +1,34 @@ +/* + * Copyright (C) 2015-2020 by Savoir-faire Linux + * Author: Edric Ladent Milaret + * + * 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 . + */ + +#pragma once + +namespace SettingsKey { + +constexpr static char closeOrMinimized[] = "closeOrMin"; +constexpr static char downloadPath[] = "downloadPath"; +constexpr static char enableNotifications[] = "enableNotifications"; +constexpr static char geometry[] = "geometry"; +constexpr static char selectedAccount[] = "selectedAccount"; +constexpr static char mainSplitterState[] = "mainSplitterState"; +constexpr static char smartListToWebviewSplitterState[] = "smartListToWebviewSplitterState"; +constexpr static char windowState[] = "windowState"; +constexpr static char autoUpdate[] = "autoUpdate"; +constexpr static char neverShowMeAgain[] = "neverShowMeAgain"; +constexpr static char hasRun[] = "hasRun"; +} // namespace SettingsKey diff --git a/src/settingsview/SettingsView.qml b/src/settingsview/SettingsView.qml new file mode 100644 index 00000000..3cc0f777 --- /dev/null +++ b/src/settingsview/SettingsView.qml @@ -0,0 +1,290 @@ +/* + * Copyright (C) 2019-2020 by Savoir-faire Linux + * Author: Yang Wang + * + * 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 . + */ + +import QtQuick 2.15 +import QtQuick.Window 2.14 +import QtQuick.Controls 2.14 +import QtQuick.Controls.Universal 2.12 +import QtQuick.Layouts 1.3 +import QtGraphicalEffects 1.14 +import net.jami.Models 1.0 + +import "components" + +Rectangle { + id: settingsViewWindow + + enum SettingsMenu{ + Account, + General, + Media, + Plugin + } + + onVisibleChanged: { + if(visible){ + setSelected(selectedMenu,true) + } + } + + function setSelected(sel, recovery = false){ + profileType = ClientWrapper.settingsAdaptor.getCurrentAccount_Profile_Info_Type() + + if(selectedMenu === sel && (!recovery)){return} + switch(sel){ + case SettingsView.Account: + currentAccountSettingsScrollWidget.connectCurrentAccount() + + avSettings.stopAudioMeter() + avSettings.stopPreviewing() + + selectedMenu = sel + + if(!settingsViewRect.isSIP){ + if(currentAccountSettingsScrollWidget.isPhotoBoothOpened()) + { + currentAccountSettingsScrollWidget.setAvatar() + } + + currentAccountSettingsScrollWidget.updateAccountInfoDisplayed() + } else { + if(currentSIPAccountSettingsScrollWidget.isPhotoBoothOpened()) { + currentSIPAccountSettingsScrollWidget.setAvatar() + } + currentSIPAccountSettingsScrollWidget.updateAccountInfoDisplayed() + } + break + case SettingsView.General: + try{ + avSettings.stopAudioMeter() + avSettings.stopPreviewing() + } catch(erro){} + + selectedMenu = sel + generalSettings.populateGeneralSettings() + break + case SettingsView.Media: + selectedMenu = sel + + avSettings.stopPreviewing() + avSettings.populateAVSettings() + avSettings.startAudioMeter() + break + case SettingsView.Plugin: + try{ + avSettings.stopAudioMeter() + avSettings.stopPreviewing() + } catch(erro){} + + selectedMenu = sel + pluginSettings.populatePluginSettings() + break + } + } + + Connections{ + id: accountListChangedConnection + target: ClientWrapper.lrcInstance + + function onAccountListChanged(){ + slotAccountListChanged() + accountListChangedConnection.enabled = false + } + } + + // slots + function leaveSettingsSlot(accountDeleted = false, showMainView = true){ + avSettings.stopAudioMeter() + avSettings.stopPreviewing() + if(!settingsViewRect.isSIP){ + currentAccountSettingsScrollWidget.stopBooth() + } else { + currentSIPAccountSettingsScrollWidget.stopBooth() + } + if (showMainView) + settingsViewWindowNeedToShowMainViewWindow(accountDeleted) + else + settingsViewWindowNeedToShowNewWizardWindow() + } + + function slotAccountListChanged(){ + var accountList = ClientWrapper.accountModel.getAccountList() + if(accountList.length === 0) { + setSelected(SettingsView.Account) + } else { + currentAccountSettingsScrollWidget.disconnectAccountConnections() + } + var device = ClientWrapper.avmodel.getDefaultDevice() + if(device.length === 0){ + ClientWrapper.avmodel.setCurrentVideoCaptureDevice(device) + } + } + property int profileType: ClientWrapper.settingsAdaptor.getCurrentAccount_Profile_Info_Type() + + + property int selectedMenu: SettingsView.Account + /* + * signal to redirect the page to main view + */ + signal settingsViewWindowNeedToShowMainViewWindow(bool accountDeleted) + signal settingsViewWindowNeedToShowNewWizardWindow + + property int textFontSize: 9 + + visible: true + + Rectangle { + id: settingsViewRect + anchors.fill: parent + + property bool isSIP: { + switch (profileType) { + case Profile.Type.SIP: + return true; + default: + return false; + } + } + + SplitView { + anchors.fill: parent + orientation: Qt.Horizontal + + handle: Rectangle { + implicitWidth: 3 + implicitHeight: 3 + color: JamiTheme.lightGrey_ + } + + Rectangle { + id: leftSettingsWidget + + SplitView.minimumWidth: 200 + SplitView.preferredWidth: 200 + SplitView.maximumWidth: parent.width / 2 + SplitView.fillHeight: true + LeftPanelView { + id: leftPanelView + + contentViewportWidth: leftSettingsWidget.width + contentViewPortHeight: leftSettingsWidget.height + + onBtnExitClicked:{ + leaveSettingsSlot() + } + + Connections { + target: leftPanelView.btnAccountSettings + function onCheckedToggledForRightPanel(checked) { + setSelected(SettingsView.Account) + } + } + Connections { + target: leftPanelView.btnGeneralSettings + function onCheckedToggledForRightPanel(checked) { + setSelected(SettingsView.General) + } + } + Connections { + target: leftPanelView.btnMediaSettings + function onCheckedToggledForRightPanel(checked) { + setSelected(SettingsView.Media) + } + } + Connections { + target: leftPanelView.btnPluginSettings + function onCheckedToggledForRightPanel(checked) { + setSelected(SettingsView.Plugin) + } + } + } + } + + StackLayout { + id: rightSettingsWidget + + property int pageIdCurrentAccountSettingsScrollPage: 0 + property int pageIdCurrentSIPAccountSettingScrollPage: 1 + property int pageIdGeneralSettingsPage: 2 + property int pageIdAvSettingPage: 3 + property int pageIdPluginSettingsPage: 4 + + currentIndex: { + switch(selectedMenu){ + case SettingsView.Account: + if(settingsViewRect.isSIP){ + return pageIdCurrentSIPAccountSettingScrollPage + } else { + return pageIdCurrentAccountSettingsScrollPage + } + case SettingsView.General: + return pageIdGeneralSettingsPage + case SettingsView.Media: + return pageIdAvSettingPage + case SettingsView.Plugin: + return pageIdPluginSettingsPage + } + } + + SplitView.fillWidth: true + SplitView.fillHeight: true + + // current account setting scroll page, index 0 + CurrentAccountSettingsScrollPage { + id: currentAccountSettingsScrollWidget + + onNavigateToMainView:{ + leaveSettingsSlot(true) + } + + onNavigateToNewWizardView: { + leaveSettingsSlot(true, false) + } + } + + // current SIP account setting scroll page, index 1 + CurrentSIPAccountSettingScrollPage { + id: currentSIPAccountSettingsScrollWidget + + onNavigateToMainView: { + leaveSettingsSlot(true) + } + + onNavigateToNewWizardView: { + leaveSettingsSlot(true, false) + } + } + + // general setting page, index 2 + GeneralSettingsPage { + id: generalSettings + } + + // av setting page, index 3 + AvSettingPage { + id: avSettings + } + + // plugin setting page, index 4 + PluginSettingsPage { + id: pluginSettings + } + } + } + } +} diff --git a/src/settingsview/components/AdvancedSIPSettingsView.qml b/src/settingsview/components/AdvancedSIPSettingsView.qml new file mode 100644 index 00000000..5ebcf84a --- /dev/null +++ b/src/settingsview/components/AdvancedSIPSettingsView.qml @@ -0,0 +1,2554 @@ +/* + * Copyright (C) 2019-2020 by Savoir-faire Linux + * Author: Yang Wang + * + * 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 . + */ + +import QtQuick 2.15 +import QtQuick.Window 2.14 +import QtQuick.Controls 2.14 +import QtQuick.Controls.Universal 2.12 +import QtQuick.Layouts 1.3 +import QtGraphicalEffects 1.14 +import QtQuick.Controls.Styles 1.4 +import QtQuick.Dialogs 1.3 +import Qt.labs.platform 1.1 +import net.jami.Models 1.0 + +import "../../commoncomponents" + +ColumnLayout { + function updateAccountInfoDisplayedAdvanceSIP(){ + // Call Settings + checkBoxAutoAnswerSIP.checked = ClientWrapper.settingsAdaptor.getAccountConfig_AutoAnswer() + checkBoxCustomRingtoneSIP.checked = ClientWrapper.settingsAdaptor.getAccountConfig_Ringtone_RingtoneEnabled() + + // security + btnSIPCACert.enabled = ClientWrapper.settingsAdaptor.getAccountConfig_TLS_Enable() + btnSIPUserCert.enabled = ClientWrapper.settingsAdaptor.getAccountConfig_TLS_Enable() + btnSIPPrivateKey.enabled = ClientWrapper.settingsAdaptor.getAccountConfig_TLS_Enable() + lineEditSIPCertPassword.enabled = ClientWrapper.settingsAdaptor.getAccountConfig_TLS_Enable() + enableSDESToggle.enabled = ClientWrapper.settingsAdaptor.getAccountConfig_SRTP_Enabled() + fallbackRTPToggle.enabled = ClientWrapper.settingsAdaptor.getAccountConfig_SRTP_Enabled() + + btnSIPCACert.text = ClientWrapper.utilsAdaptor.toFileInfoName(ClientWrapper.settingsAdaptor.getAccountConfig_TLS_CertificateListFile()) + btnSIPUserCert.text = ClientWrapper.utilsAdaptor.toFileInfoName(ClientWrapper.settingsAdaptor.getAccountConfig_TLS_CertificateFile()) + btnSIPPrivateKey.text = ClientWrapper.utilsAdaptor.toFileInfoName(ClientWrapper.settingsAdaptor.getAccountConfig_TLS_PrivateKeyFile()) + lineEditSIPCertPassword.text = ClientWrapper.settingsAdaptor.getAccountConfig_TLS_Password() + + encryptMediaStreamsToggle.checked = ClientWrapper.settingsAdaptor.getAccountConfig_SRTP_Enabled() + enableSDESToggle.checked = (ClientWrapper.settingsAdaptor.getAccountConfig_SRTP_KeyExchange() === Account.KeyExchangeProtocol.SDES) + fallbackRTPToggle.checked = ClientWrapper.settingsAdaptor.getAccountConfig_SRTP_RtpFallback() + encryptNegotitationToggle.checked = ClientWrapper.settingsAdaptor.getAccountConfig_TLS_Enable() + verifyIncomingCertificatesServerToogle.checked = ClientWrapper.settingsAdaptor.getAccountConfig_TLS_VerifyServer() + verifyIncomingCertificatesClientToogle.checked = ClientWrapper.settingsAdaptor.getAccountConfig_TLS_VerifyClient() + requireCeritificateForTLSIncomingToggle.checked = ClientWrapper.settingsAdaptor.getAccountConfig_TLS_RequireClientCertificate() + + var method = ClientWrapper.settingsAdaptor.getAccountConfig_TLS_Method_inInt() + tlsProtocolComboBox.currentIndex = method + + outgoingTLSServerNameLineEdit.text = ClientWrapper.settingsAdaptor.getAccountConfig_TLS_Servername() + negotiationTimeoutSpinBox.value = ClientWrapper.settingsAdaptor.getAccountConfig_TLS_NegotiationTimeoutSec() + + // Connectivity + checkBoxUPnPSIP.checked = ClientWrapper.settingsAdaptor.getAccountConfig_UpnpEnabled() + checkBoxTurnEnableSIP.checked = ClientWrapper.settingsAdaptor.getAccountConfig_TURN_Enabled() + lineEditTurnAddressSIP.text = ClientWrapper.settingsAdaptor.getAccountConfig_TURN_Server() + lineEditTurnUsernameSIP.text = ClientWrapper.settingsAdaptor.getAccountConfig_TURN_Username() + lineEditTurnPsswdSIP.text = ClientWrapper.settingsAdaptor.getAccountConfig_TURN_Password() + lineEditTurnRealmSIP.text = ClientWrapper.settingsAdaptor.getAccountConfig_TURN_Realm() + lineEditTurnAddressSIP.enabled = ClientWrapper.settingsAdaptor.getAccountConfig_TURN_Enabled() + lineEditTurnUsernameSIP.enabled = ClientWrapper.settingsAdaptor.getAccountConfig_TURN_Enabled() + lineEditTurnPsswdSIP.enabled = ClientWrapper.settingsAdaptor.getAccountConfig_TURN_Enabled() + lineEditTurnRealmSIP.enabled = ClientWrapper.settingsAdaptor.getAccountConfig_TURN_Enabled() + + checkBoxSTUNEnableSIP.checked = ClientWrapper.settingsAdaptor.getAccountConfig_STUN_Enabled() + lineEditSTUNAddressSIP.text = ClientWrapper.settingsAdaptor.getAccountConfig_STUN_Server() + lineEditSTUNAddressSIP.enabled = ClientWrapper.settingsAdaptor.getAccountConfig_STUN_Enabled() + + registrationExpireTimeoutSpinBox.value = ClientWrapper.settingsAdaptor.getAccountConfig_Registration_Expire() + networkInterfaceSpinBox.value = ClientWrapper.settingsAdaptor.getAccountConfig_Localport() + + // published address + checkBoxCustomAddressPort.checked = ClientWrapper.settingsAdaptor.getAccountConfig_PublishedSameAsLocal() + lineEditSIPCustomAddress.text = ClientWrapper.settingsAdaptor.getAccountConfig_PublishedAddress() + customPortSIPSpinBox.value = ClientWrapper.settingsAdaptor.getAccountConfig_PublishedPort() + + // codecs + videoCheckBoxSIP.checked = ClientWrapper.settingsAdaptor.getAccountConfig_Video_Enabled() + updateAudioCodecs() + updateVideoCodecs() + btnRingtoneSIP.enabled = ClientWrapper.settingsAdaptor.getAccountConfig_Ringtone_RingtoneEnabled() + btnRingtoneSIP.text = ClientWrapper.utilsAdaptor.toFileInfoName(ClientWrapper.settingsAdaptor.getAccountConfig_Ringtone_RingtonePath()) + lineEditSTUNAddressSIP.enabled = ClientWrapper.settingsAdaptor.getAccountConfig_STUN_Enabled() + + // SDP session negotiation ports + audioRTPMinPortSpinBox.value = ClientWrapper.settingsAdaptor.getAccountConfig_Audio_AudioPortMin() + audioRTPMaxPortSpinBox.value = ClientWrapper.settingsAdaptor.getAccountConfig_Audio_AudioPortMax() + videoRTPMinPortSpinBox.value = ClientWrapper.settingsAdaptor.getAccountConfig_Video_VideoPortMin() + videoRTPMaxPortSpinBox.value = ClientWrapper.settingsAdaptor.getAccountConfig_Video_VideoPortMax() + + // voicemail + lineEditVoiceMailDialCode.text = ClientWrapper.settingsAdaptor.getAccountConfig_Mailbox() + } + + function updateAudioCodecs(){ + audioCodecListModelSIP.layoutAboutToBeChanged() + audioCodecListModelSIP.dataChanged(audioCodecListModelSIP.index(0, 0), + audioCodecListModelSIP.index(audioCodecListModelSIP.rowCount() - 1, 0)) + audioCodecListModelSIP.layoutChanged() + } + + function updateVideoCodecs(){ + videoCodecListModelSIP.layoutAboutToBeChanged() + videoCodecListModelSIP.dataChanged(videoCodecListModelSIP.index(0, 0), + videoCodecListModelSIP.index(videoCodecListModelSIP.rowCount() - 1, 0)) + videoCodecListModelSIP.layoutChanged() + } + + function decreaseAudioCodecPriority(){ + var index = audioListWidgetSIP.currentIndex + var codecId = audioCodecListModelSIP.data(audioCodecListModelSIP.index(index,0), AudioCodecListModel.AudioCodecID) + + ClientWrapper.settingsAdaptor.decreaseAudioCodecPriority(codecId) + audioListWidgetSIP.currentIndex = index + 1 + updateAudioCodecs() + } + + function increaseAudioCodecPriority(){ + var index = audioListWidgetSIP.currentIndex + var codecId = audioCodecListModelSIP.data(audioCodecListModelSIP.index(index,0), AudioCodecListModel.AudioCodecID) + + ClientWrapper.settingsAdaptor.increaseAudioCodecPriority(codecId) + audioListWidgetSIP.currentIndex = index - 1 + updateAudioCodecs() + } + + function decreaseVideoCodecPriority(){ + var index = videoListWidgetSIP.currentIndex + var codecId = videoCodecListModelSIP.data(videoCodecListModelSIP.index(index,0), VideoCodecListModel.VideoCodecID) + + ClientWrapper.settingsAdaptor.decreaseVideoCodecPriority(codecId) + videoListWidgetSIP.currentIndex = index + 1 + updateVideoCodecs() + } + + function increaseVideoCodecPriority(){ + var index = videoListWidgetSIP.currentIndex + var codecId = videoCodecListModelSIP.data(videoCodecListModelSIP.index(index,0), VideoCodecListModel.VideoCodecID) + + ClientWrapper.settingsAdaptor.increaseVideoCodecPriority(codecId) + videoListWidgetSIP.currentIndex = index - 1 + updateVideoCodecs() + } + + VideoCodecListModel{ + id: videoCodecListModelSIP + } + + AudioCodecListModel{ + id: audioCodecListModelSIP + } + + + // slots + function audioRTPMinPortSpinBoxEditFinished(value){ + if (ClientWrapper.settingsAdaptor.getAccountConfig_Audio_AudioPortMax() < value) { + audioRTPMinPortSpinBox.value = ClientWrapper.settingsAdaptor.getAccountConfig_Audio_AudioPortMin() + return + } + ClientWrapper.settingsAdaptor.audioRTPMinPortSpinBoxEditFinished(value) + } + + function audioRTPMaxPortSpinBoxEditFinished(value){ + if (value < ClientWrapper.settingsAdaptor.getAccountConfig_Audio_AudioPortMin()) { + audioRTPMaxPortSpinBox.value = ClientWrapper.settingsAdaptor.getAccountConfig_Audio_AudioPortMax() + return + } + ClientWrapper.settingsAdaptor.audioRTPMaxPortSpinBoxEditFinished(value) + } + + function videoRTPMinPortSpinBoxEditFinished(value){ + if (ClientWrapper.settingsAdaptor.getAccountConfig_Video_VideoPortMax() < value) { + videoRTPMinPortSpinBox.value = ClientWrapper.settingsAdaptor.getAccountConfig_Video_VideoPortMin() + return + } + ClientWrapper.settingsAdaptor.videoRTPMinPortSpinBoxEditFinished(value) + } + + function videoRTPMaxPortSpinBoxEditFinished(value){ + if (value < ClientWrapper.settingsAdaptor.getAccountConfig_Video_VideoPortMin()) { + videoRTPMinPortSpinBox.value = ClientWrapper.settingsAdaptor.getAccountConfig_Video_VideoPortMin() + return + } + ClientWrapper.settingsAdaptor.videoRTPMaxPortSpinBoxEditFinished(value) + } + + + function changeRingtonePath(url){ + if(url.length !== 0) { + ClientWrapper.settingsAdaptor.set_RingtonePath(url) + btnRingtoneSIP.text = ClientWrapper.utilsAdaptor.toFileInfoName(ClientWrapper.settingsAdaptor.getAccountConfig_Ringtone_RingtonePath()) + } else if (ClientWrapper.settingsAdaptor.getAccountConfig_Ringtone_RingtonePath().length === 0){ + btnRingtoneSIP.text = qsTr("Add a custom ringtone") + } + } + + function changeFileCACert(url){ + if(url.length !== 0) { + ClientWrapper.settingsAdaptor.set_FileCACert(url) + btnSIPCACert.text = ClientWrapper.utilsAdaptor.toFileInfoName(ClientWrapper.settingsAdaptor.getAccountConfig_TLS_CertificateListFile()) + } + } + + function changeFileUserCert(url){ + if(url.length !== 0) { + ClientWrapper.settingsAdaptor.set_FileUserCert(url) + btnSIPUserCert.text = ClientWrapper.utilsAdaptor.toFileInfoName(ClientWrapper.settingsAdaptor.getAccountConfig_TLS_CertificateFile()) + } + } + + function changeFilePrivateKey(url){ + if(url.length !== 0) { + ClientWrapper.settingsAdaptor.set_FilePrivateKey(url) + btnSIPPrivateKey.text = ClientWrapper.utilsAdaptor.toFileInfoName(ClientWrapper.settingsAdaptor.getAccountConfig_TLS_PrivateKeyFile()) + } + } + + JamiFileDialog { + id: ringtonePath_Dialog_SIP + + property string oldPath : ClientWrapper.settingsAdaptor.getAccountConfig_Ringtone_RingtonePath() + property string openPath : oldPath === "" ? (ClientWrapper.utilsAdaptor.getCurrentPath() + "/ringtones/") : (ClientWrapper.utilsAdaptor.toFileAbsolutepath(oldPath)) + + mode: JamiFileDialog.OpenFile + title: qsTr("Select a new ringtone") + folder: openPath + + nameFilters: [qsTr("Audio Files") + " (*.wav *.ogg *.opus *.mp3 *.aiff *.wma)", qsTr( + "All files") + " (*)"] + + onRejected: {} + + onVisibleChanged: { + if (!visible) { + rejected() + } + } + + onAccepted: { + var url = ClientWrapper.utilsAdaptor.getAbsPath(file.toString()) + changeRingtonePath(url) + } + } + + JamiFileDialog { + id: caCert_Dialog_SIP + + property string oldPath : ClientWrapper.settingsAdaptor.getAccountConfig_TLS_CertificateListFile() + property string openPath : oldPath === "" ? (ClientWrapper.utilsAdaptor.getCurrentPath() + "/ringtones/") : (ClientWrapper.utilsAdaptor.toFileAbsolutepath(oldPath)) + + mode: JamiFileDialog.OpenFile + title: qsTr("Select a CA certificate") + folder: openPath + nameFilters: [qsTr("Certificate File") + " (*.crt)", qsTr( + "All files") + " (*)"] + + onRejected: {} + + onVisibleChanged: { + if (!visible) { + rejected() + } + } + + onAccepted: { + var url = ClientWrapper.utilsAdaptor.getAbsPath(file.toString()) + changeFileCACert(url) + } + } + + JamiFileDialog { + id: userCert_Dialog_SIP + + property string oldPath : ClientWrapper.settingsAdaptor.getAccountConfig_TLS_CertificateFile() + property string openPath : oldPath === "" ? (ClientWrapper.utilsAdaptor.getCurrentPath() + "/ringtones/") : (ClientWrapper.utilsAdaptor.toFileAbsolutepath(oldPath)) + + mode: JamiFileDialog.OpenFile + title: qsTr("Select a user certificate") + folder: openPath + nameFilters: [qsTr("Certificate File") + " (*.crt)", qsTr( + "All files") + " (*)"] + + onRejected: {} + + onVisibleChanged: { + if (!visible) { + rejected() + } + } + + onAccepted: { + var url = ClientWrapper.utilsAdaptor.getAbsPath(file.toString()) + changeFileUserCert(url) + } + } + + JamiFileDialog { + id: privateKey_Dialog_SIP + + property string oldPath : ClientWrapper.settingsAdaptor.getAccountConfig_TLS_PrivateKeyFile() + property string openPath : oldPath === "" ? (ClientWrapper.utilsAdaptor.getCurrentPath() + "/ringtones/") : (ClientWrapper.utilsAdaptor.toFileAbsolutepath(oldPath)) + + mode: JamiFileDialog.OpenFile + title: qsTr("Select a private key") + folder: openPath + nameFilters: [qsTr("Key File") + " (*.key)", qsTr( + "All files") + " (*)"] + + onRejected: {} + + onVisibleChanged: { + if (!visible) { + rejected() + } + } + + onAccepted: { + var url = ClientWrapper.utilsAdaptor.getAbsPath(file.toString()) + changeFilePrivateKey(url) + } + } + + spacing: 6 + Layout.preferredWidth: 532 + Layout.maximumWidth: 532 + + Item { + Layout.fillWidth: true + + Layout.minimumHeight: 24 + Layout.preferredHeight: 24 + Layout.maximumHeight: 24 + } + + // call setting section + ColumnLayout { + spacing: 6 + Layout.fillWidth: true + + Label { + Layout.fillWidth: true + + Layout.minimumHeight: 27 + Layout.preferredHeight: 27 + Layout.maximumHeight: 27 + + text: qsTr("Call Settings") + + font.pointSize: 13 + font.kerning: true + + horizontalAlignment: Text.AlignLeft + verticalAlignment: Text.AlignVCenter + } + + ColumnLayout { + spacing: 6 + Layout.fillWidth: true + Layout.leftMargin: 20 + + ToggleSwitch { + id: checkBoxAutoAnswerSIP + labelText: qsTr("Auto Answer Call") + fontPointSize: 10 + + Layout.leftMargin: 20 + + onSwitchToggled: { + ClientWrapper.settingsAdaptor.setAutoAnswerCalls(checked) + } + } + + RowLayout { + Layout.fillWidth: true + Layout.leftMargin: 20 + Layout.maximumHeight: 30 + + ToggleSwitch { + id: checkBoxCustomRingtoneSIP + labelText: qsTr("Enable Custom Ringtone") + fontPointSize: 10 + + Layout.maximumWidth: 164 + Layout.preferredWidth: 164 + Layout.minimumWidth: 164 + + onSwitchToggled: { + ClientWrapper.settingsAdaptor.setEnableRingtone(checked) + btnRingtoneSIP.enabled = checked + } + } + + Item { + Layout.fillHeight: true + Layout.fillWidth: true + } + + HoverableRadiusButton { + id: btnRingtoneSIP + + radius: height / 2 + + Layout.maximumWidth: 164 + Layout.preferredWidth: 164 + Layout.minimumWidth: 164 + + Layout.maximumHeight: 30 + Layout.preferredHeight: 30 + Layout.minimumHeight: 30 + + icon.source: "qrc:/images/icons/round-folder-24px.svg" + icon.width: 16 + icon.height: 16 + + onClicked: { + ringtonePath_Dialog_SIP.open() + } + } + } + } + } + + Item { + Layout.fillWidth: true + + Layout.minimumHeight: 20 + Layout.preferredHeight: 20 + Layout.maximumHeight: 20 + } + + // voice mail section + ColumnLayout { + spacing: 6 + Layout.fillWidth: true + + Label { + Layout.fillWidth: true + + Layout.minimumHeight: 27 + Layout.preferredHeight: 27 + Layout.maximumHeight: 27 + + text: qsTr("Voicemail") + + font.pointSize: 13 + font.kerning: true + + horizontalAlignment: Text.AlignLeft + verticalAlignment: Text.AlignVCenter + } + + Item { + Layout.fillWidth: true + + Layout.minimumHeight: 13 + Layout.preferredHeight: 13 + Layout.maximumHeight: 13 + } + + RowLayout { + Layout.fillWidth: true + Layout.leftMargin: 20 + Layout.maximumHeight: 30 + + Label { + Layout.maximumWidth: 162 + Layout.preferredWidth: 162 + Layout.minimumWidth: 162 + + Layout.minimumHeight: 28 + Layout.preferredHeight: 28 + Layout.maximumHeight: 28 + + text: qsTr("Voicemail Dial Code") + font.pointSize: 10 + font.kerning: true + + horizontalAlignment: Text.AlignLeft + verticalAlignment: Text.AlignVCenter + } + + Item { + Layout.fillHeight: true + Layout.fillWidth: true + } + + InfoLineEdit { + id: lineEditVoiceMailDialCode + + fieldLayoutWidth: 250 + + font.pointSize: 10 + font.kerning: true + + horizontalAlignment: Text.AlignLeft + verticalAlignment: Text.AlignVCenter + + onEditingFinished: { + ClientWrapper.settingsAdaptor.lineEditVoiceMailDialCodeEditFinished(text) + } + } + } + } + + Item { + Layout.fillWidth: true + + Layout.minimumHeight: 20 + Layout.preferredHeight: 20 + Layout.maximumHeight: 20 + } + + // security section + ColumnLayout { + spacing: 6 + Layout.fillWidth: true + + Label { + Layout.fillWidth: true + + Layout.minimumHeight: 27 + Layout.preferredHeight: 27 + Layout.maximumHeight: 27 + + text: qsTr("Security") + + font.pointSize: 13 + font.kerning: true + + horizontalAlignment: Text.AlignLeft + verticalAlignment: Text.AlignVCenter + } + + Item { + Layout.fillWidth: true + + Layout.maximumHeight: 13 + Layout.preferredHeight: 13 + Layout.minimumHeight: 13 + } + + GridLayout { + Layout.leftMargin: 20 + Layout.fillWidth: true + + rowSpacing: 6 + columnSpacing: 6 + + rows: 14 + columns: 3 + + // First row + ToggleSwitch{ + id: encryptMediaStreamsToggle + + labelText: qsTr("Encrypt Media Streams(SRTP)") + fontPointSize: 10 + + Layout.row: 0 + Layout.column: 0 + + onSwitchToggled: { + ClientWrapper.settingsAdaptor.setUseSRTP(checked) + enableSDESToggle.enabled = checked + fallbackRTPToggle.enabled = checked + } + } + + Item{ + Layout.fillHeight: true + + Layout.maximumWidth: 20 + Layout.preferredWidth: 20 + Layout.minimumWidth: 20 + + Layout.row: 0 + Layout.column: 1 + } + + // second row + ToggleSwitch{ + id: enableSDESToggle + + labelText: qsTr("Enable SDES(Key Exchange)") + fontPointSize: 10 + + Layout.row: 1 + Layout.column: 0 + + onSwitchToggled: { + ClientWrapper.settingsAdaptor.setUseSDES(checked) + } + } + + Item{ + Layout.fillHeight: true + + Layout.maximumWidth: 20 + Layout.preferredWidth: 20 + Layout.minimumWidth: 20 + + Layout.row: 1 + Layout.column: 1 + } + + // third row + ToggleSwitch{ + id: fallbackRTPToggle + + labelText: qsTr("Can Fallback on RTP") + fontPointSize: 10 + + Layout.row: 2 + Layout.column: 0 + + onSwitchToggled: { + ClientWrapper.settingsAdaptor.setUseRTPFallback(checked) + } + } + + Item{ + Layout.fillHeight: true + + Layout.maximumWidth: 20 + Layout.preferredWidth: 20 + Layout.minimumWidth: 20 + + Layout.row: 2 + Layout.column: 1 + } + + // fourth row + ToggleSwitch{ + id: encryptNegotitationToggle + + labelText: qsTr("Encrypt Negotiation(TLS)") + fontPointSize: 10 + + Layout.row: 3 + Layout.column: 0 + + onSwitchToggled: { + ClientWrapper.settingsAdaptor.setUseTLS(checked) + btnSIPCACert.enabled = checked + btnSIPUserCert.enabled = checked + btnSIPPrivateKey.enabled = checked + lineEditSIPCertPassword.enabled = checked + } + } + + Item{ + Layout.fillHeight: true + + Layout.maximumWidth: 20 + Layout.preferredWidth: 20 + Layout.minimumWidth: 20 + + Layout.row: 3 + Layout.column: 1 + } + + // fifth row + RowLayout{ + spacing: 6 + Layout.maximumHeight: 30 + + Layout.row: 4 + Layout.column: 0 + + Item{ + Layout.fillHeight: true + + Layout.maximumWidth: 20 + Layout.preferredWidth: 20 + Layout.minimumWidth: 20 + } + + Label{ + Layout.maximumHeight: 30 + Layout.preferredHeight: 30 + Layout.minimumHeight: 30 + + Layout.maximumWidth: 209 + Layout.preferredWidth: 209 + Layout.minimumWidth: 209 + + text: qsTr("CA Certificate") + + font.pointSize: 10 + font.kerning: true + + horizontalAlignment: Text.AlignLeft + verticalAlignment: Text.AlignVCenter + } + } + + Item{ + Layout.fillHeight: true + + Layout.maximumWidth: 20 + Layout.preferredWidth: 20 + Layout.minimumWidth: 20 + + Layout.row: 4 + Layout.column: 1 + } + + HoverableRadiusButton{ + id: btnSIPCACert + + Layout.maximumHeight: 30 + Layout.preferredHeight: 30 + Layout.minimumHeight: 30 + + Layout.maximumWidth: 250 + Layout.preferredWidth: 250 + Layout.minimumWidth: 250 + + radius: height / 2 + + icon.source: "qrc:/images/icons/round-folder-24px.svg" + icon.width: 16 + icon.height: 16 + + Layout.row: 4 + Layout.column: 2 + + onClicked: { + caCert_Dialog_SIP.open() + } + } + + // sixth row + RowLayout{ + spacing: 6 + Layout.maximumHeight: 30 + + Layout.row: 5 + Layout.column: 0 + + Item{ + Layout.fillHeight: true + + Layout.maximumWidth: 20 + Layout.preferredWidth: 20 + Layout.minimumWidth: 20 + } + + Label{ + Layout.maximumHeight: 30 + Layout.preferredHeight: 30 + Layout.minimumHeight: 30 + + Layout.maximumWidth: 209 + Layout.preferredWidth: 209 + Layout.minimumWidth: 209 + + text: qsTr("User Certificate") + + font.pointSize: 10 + font.kerning: true + + horizontalAlignment: Text.AlignLeft + verticalAlignment: Text.AlignVCenter + } + } + + Item{ + Layout.fillHeight: true + + Layout.maximumWidth: 20 + Layout.preferredWidth: 20 + Layout.minimumWidth: 20 + + Layout.row: 5 + Layout.column: 1 + } + + HoverableRadiusButton{ + id: btnSIPUserCert + + Layout.maximumHeight: 30 + Layout.preferredHeight: 30 + Layout.minimumHeight: 30 + + Layout.maximumWidth: 250 + Layout.preferredWidth: 250 + Layout.minimumWidth: 250 + + radius: height / 2 + + icon.source: "qrc:/images/icons/round-folder-24px.svg" + icon.width: 16 + icon.height: 16 + + Layout.row: 5 + Layout.column: 2 + + onClicked: { + userCert_Dialog_SIP.open() + } + } + + // seventh row + RowLayout{ + spacing: 6 + Layout.maximumHeight: 30 + + Layout.row: 6 + Layout.column: 0 + + Item{ + Layout.fillHeight: true + + Layout.maximumWidth: 20 + Layout.preferredWidth: 20 + Layout.minimumWidth: 20 + } + + Label{ + Layout.maximumHeight: 30 + Layout.preferredHeight: 30 + Layout.minimumHeight: 30 + + Layout.maximumWidth: 209 + Layout.preferredWidth: 209 + Layout.minimumWidth: 209 + + text: qsTr("Private Key") + + font.pointSize: 10 + font.kerning: true + + horizontalAlignment: Text.AlignLeft + verticalAlignment: Text.AlignVCenter + } + } + + Item{ + Layout.fillHeight: true + + Layout.maximumWidth: 20 + Layout.preferredWidth: 20 + Layout.minimumWidth: 20 + + Layout.row: 6 + Layout.column: 1 + } + + HoverableRadiusButton{ + id: btnSIPPrivateKey + + Layout.maximumHeight: 30 + Layout.preferredHeight: 30 + Layout.minimumHeight: 30 + + Layout.maximumWidth: 250 + Layout.preferredWidth: 250 + Layout.minimumWidth: 250 + + radius: height / 2 + + icon.source: "qrc:/images/icons/round-folder-24px.svg" + icon.width: 16 + icon.height: 16 + + Layout.row: 6 + Layout.column: 2 + + onClicked: { + privateKey_Dialog_SIP.open() + } + } + + // eight row + RowLayout{ + spacing: 6 + Layout.maximumHeight: 30 + + Layout.row: 7 + Layout.column: 0 + + Item{ + Layout.fillHeight: true + + Layout.maximumWidth: 20 + Layout.preferredWidth: 20 + Layout.minimumWidth: 20 + } + + Label{ + Layout.maximumHeight: 30 + Layout.preferredHeight: 30 + Layout.minimumHeight: 30 + + Layout.maximumWidth: 209 + Layout.preferredWidth: 209 + Layout.minimumWidth: 209 + + text: qsTr("Private Key Password") + + font.pointSize: 10 + font.kerning: true + + horizontalAlignment: Text.AlignLeft + verticalAlignment: Text.AlignVCenter + } + } + + Item{ + Layout.fillHeight: true + + Layout.maximumWidth: 20 + Layout.preferredWidth: 20 + Layout.minimumWidth: 20 + + Layout.row: 7 + Layout.column: 1 + } + + InfoLineEdit { + id: lineEditSIPCertPassword + + Layout.alignment: Qt.AlignCenter + + fieldLayoutWidth: 250 + fieldLayoutHeight: 29 + + font.pointSize: 10 + font.kerning: true + + horizontalAlignment: Text.AlignLeft + verticalAlignment: Text.AlignVCenter + + echoMode: TextInput.Password + + Layout.row: 7 + Layout.column: 2 + + onEditingFinished: { + ClientWrapper.settingsAdaptor.lineEditSIPCertPasswordLineEditTextChanged(text) + } + } + + // nineth row + ToggleSwitch{ + id: verifyIncomingCertificatesServerToogle + + labelText: qsTr("Verify Certificates(Server Side)") + fontPointSize: 10 + + Layout.row: 8 + Layout.column: 0 + + onSwitchToggled: { + ClientWrapper.settingsAdaptor.setVerifyCertificatesServer(checked) + } + } + + Item{ + Layout.fillHeight: true + + Layout.maximumWidth: 20 + Layout.preferredWidth: 20 + Layout.minimumWidth: 20 + + Layout.row: 8 + Layout.column: 1 + } + + // tenth row + ToggleSwitch{ + id: verifyIncomingCertificatesClientToogle + + labelText: qsTr("Verify Certificates(Client Side)") + fontPointSize: 10 + + Layout.row: 9 + Layout.column: 0 + + onSwitchToggled: { + ClientWrapper.settingsAdaptor.setVerifyCertificatesClient(checked) + } + } + + Item{ + Layout.fillHeight: true + + Layout.maximumWidth: 20 + Layout.preferredWidth: 20 + Layout.minimumWidth: 20 + + Layout.row: 9 + Layout.column: 1 + } + + //eleventh row + ToggleSwitch{ + id: requireCeritificateForTLSIncomingToggle + + labelText: qsTr("TLS Connections Require Certificate") + fontPointSize: 10 + + Layout.row: 10 + Layout.column: 0 + + onSwitchToggled: { + ClientWrapper.settingsAdaptor.setRequireCertificatesIncomingTLS(checked) + } + } + + Item{ + Layout.fillHeight: true + + Layout.maximumWidth: 20 + Layout.preferredWidth: 20 + Layout.minimumWidth: 20 + + Layout.row:10 + Layout.column: 1 + } + + // twelveth row + Label{ + Layout.fillWidth: true + + Layout.maximumHeight: 30 + Layout.preferredHeight: 30 + Layout.minimumHeight: 30 + + text: qsTr("TLS Protocol Method") + font.pointSize: 10 + font.kerning: true + + horizontalAlignment: Text.AlignLeft + verticalAlignment: Text.AlignVCenter + + Layout.row: 11 + Layout.column: 0 + } + + Item{ + Layout.fillHeight: true + + Layout.maximumWidth: 20 + Layout.preferredWidth: 20 + Layout.minimumWidth: 20 + + Layout.row: 11 + Layout.column: 1 + } + + SettingParaCombobox{ + id:tlsProtocolComboBox + + Layout.maximumWidth: 252 + Layout.preferredWidth: 252 + Layout.minimumWidth: 252 + + Layout.maximumHeight: 29 + Layout.minimumHeight: 29 + Layout.preferredHeight: 29 + + Layout.alignment: Qt.AlignCenter + + font.pointSize: 10 + font.kerning: true + + Layout.row: 11 + Layout.column: 2 + + textRole: "textDisplay" + + model: ListModel{ + ListElement{textDisplay: "Default"; firstArg: "Default"; secondArg: 0} + ListElement{textDisplay: "TLSv1"; firstArg: "TLSv1"; secondArg: 1} + ListElement{textDisplay: "TLSv1.1"; firstArg: "TLSv1.1"; secondArg: 2} + ListElement{textDisplay: "TLSv1.2"; firstArg: "TLSv1.2"; secondArg: 3} + } + + onActivated: { + var indexOfOption = tlsProtocolComboBox.model.get(index).secondArg + ClientWrapper.settingsAdaptor.tlsProtocolComboBoxIndexChanged(parseInt(indexOfOption)) + } + } + + // 13th row + Label{ + Layout.fillWidth: true + + Layout.maximumHeight: 30 + Layout.preferredHeight: 30 + Layout.minimumHeight: 30 + + text: qsTr("Outgoing TLS Server Name") + font.pointSize: 10 + font.kerning: true + + horizontalAlignment: Text.AlignLeft + verticalAlignment: Text.AlignVCenter + + Layout.row: 12 + Layout.column: 0 + } + + Item{ + Layout.fillHeight: true + + Layout.maximumWidth: 20 + Layout.preferredWidth: 20 + Layout.minimumWidth: 20 + + Layout.row: 12 + Layout.column: 1 + } + + InfoLineEdit { + id: outgoingTLSServerNameLineEdit + + Layout.alignment: Qt.AlignCenter + + fieldLayoutWidth: 250 + fieldLayoutHeight: 29 + + font.pointSize: 10 + font.kerning: true + + horizontalAlignment: Text.AlignLeft + verticalAlignment: Text.AlignVCenter + + Layout.row: 12 + Layout.column: 2 + + onEditingFinished: { + ClientWrapper.settingsAdaptor.outgoingTLSServerNameLineEditTextChanged(text) + } + } + + // 14th row + Label{ + Layout.fillWidth: true + + Layout.maximumHeight: 30 + Layout.preferredHeight: 30 + Layout.minimumHeight: 30 + + text: qsTr("Negotiation Timeout(seconds)") + font.pointSize: 10 + font.kerning: true + + horizontalAlignment: Text.AlignLeft + verticalAlignment: Text.AlignVCenter + + Layout.row: 13 + Layout.column: 0 + } + + Item{ + Layout.fillHeight: true + + Layout.maximumWidth: 20 + Layout.preferredWidth: 20 + Layout.minimumWidth: 20 + + Layout.row: 13 + Layout.column: 1 + } + + SpinBox{ + id:negotiationTimeoutSpinBox + + Layout.maximumWidth: 252 + Layout.preferredWidth: 252 + Layout.minimumWidth: 252 + + Layout.maximumHeight: 30 + Layout.minimumHeight: 30 + Layout.preferredHeight: 30 + + Layout.alignment: Qt.AlignCenter + + font.pointSize: 10 + font.kerning: true + + from: 0 + to: 3000 + stepSize: 1 + + Layout.row: 13 + Layout.column: 2 + + onValueModified: { + ClientWrapper.settingsAdaptor.negotiationTimeoutSpinBoxValueChanged(value) + } + } + } + } + + Item{ + Layout.fillWidth: true + + Layout.maximumHeight: 20 + Layout.preferredHeight: 20 + Layout.minimumHeight: 20 + } + + // connectivity section + ColumnLayout{ + spacing: 6 + Layout.fillWidth: true + + Label { + Layout.fillWidth: true + + Layout.minimumHeight: 27 + Layout.preferredHeight: 27 + Layout.maximumHeight: 27 + + text: qsTr("Connectivity") + + font.pointSize: 13 + font.kerning: true + + horizontalAlignment: Text.AlignLeft + verticalAlignment: Text.AlignVCenter + } + + Item { + Layout.fillWidth: true + + Layout.maximumHeight: 10 + Layout.preferredHeight: 10 + Layout.minimumHeight: 10 + } + + GridLayout{ + Layout.leftMargin: 20 + Layout.fillWidth: true + + rowSpacing: 6 + columnSpacing: 6 + + rows: 9 + columns: 3 + + // 1st row + Label{ + Layout.minimumWidth: 286 + Layout.preferredWidth: 286 + + Layout.minimumHeight: 28 + Layout.preferredHeight: 28 + Layout.maximumHeight: 28 + + text: qsTr("Registration Expire Timeout(seconds)") + font.pointSize: 10 + font.kerning: true + + horizontalAlignment: Text.AlignLeft + verticalAlignment: Text.AlignVCenter + + Layout.row: 0 + Layout.column: 0 + } + + Item{ + Layout.fillHeight: true + + Layout.maximumWidth: 20 + Layout.preferredWidth: 20 + Layout.minimumWidth: 20 + + Layout.row: 0 + Layout.column: 1 + } + + SpinBox{ + id: registrationExpireTimeoutSpinBox + + Layout.maximumWidth: 250 + Layout.preferredWidth: 250 + Layout.minimumWidth: 250 + + Layout.maximumHeight: 30 + Layout.minimumHeight: 30 + Layout.preferredHeight: 30 + + Layout.alignment: Qt.AlignCenter + + font.pointSize: 10 + font.kerning: true + + from: 0 + to: 3000 + stepSize: 1 + + Layout.row: 0 + Layout.column: 2 + + onValueModified: { + ClientWrapper.settingsAdaptor.registrationTimeoutSpinBoxValueChanged(value) + } + } + + // 2nd row + Label{ + Layout.minimumWidth: 286 + Layout.preferredWidth: 286 + + Layout.minimumHeight: 28 + Layout.preferredHeight: 28 + Layout.maximumHeight: 28 + + text: qsTr("Newtwork interface") + font.pointSize: 10 + font.kerning: true + + horizontalAlignment: Text.AlignLeft + verticalAlignment: Text.AlignVCenter + + Layout.row: 1 + Layout.column: 0 + } + + Item{ + Layout.fillHeight: true + + Layout.maximumWidth: 20 + Layout.preferredWidth: 20 + Layout.minimumWidth: 20 + + Layout.row: 1 + Layout.column: 1 + } + + SpinBox{ + id: networkInterfaceSpinBox + + Layout.maximumWidth: 250 + Layout.preferredWidth: 250 + Layout.minimumWidth: 250 + + Layout.maximumHeight: 30 + Layout.minimumHeight: 30 + Layout.preferredHeight: 30 + + Layout.alignment: Qt.AlignCenter + + font.pointSize: 10 + font.kerning: true + + from: 0 + to: 65536 + stepSize: 1 + + Layout.row: 1 + Layout.column: 2 + + onValueModified: { + ClientWrapper.settingsAdaptor.networkInterfaceSpinBoxValueChanged(value) + } + } + + // 3rd row + ToggleSwitch{ + id: checkBoxUPnPSIP + + labelText: qsTr("Use UPnP") + fontPointSize: 10 + + Layout.row: 2 + Layout.column: 0 + + onSwitchToggled: { + ClientWrapper.settingsAdaptor.setUseUPnP(checked) + } + } + + Item{ + Layout.fillHeight: true + + Layout.maximumWidth: 20 + Layout.preferredWidth: 20 + Layout.minimumWidth: 20 + + Layout.row: 2 + Layout.column: 1 + } + + // 4th row + ToggleSwitch{ + id: checkBoxTurnEnableSIP + + labelText: qsTr("Use TURN") + fontPointSize: 10 + + Layout.row: 3 + Layout.column: 0 + + onSwitchToggled: { + ClientWrapper.settingsAdaptor.setUseTURN(checked) + lineEditTurnAddressSIP.enabled = checked + lineEditTurnUsernameSIP.enabled = checked + lineEditTurnPsswdSIP.enabled = checked + lineEditTurnRealmSIP.enabled = checked + } + } + + Item{ + Layout.fillHeight: true + + Layout.maximumWidth: 20 + Layout.preferredWidth: 20 + Layout.minimumWidth: 20 + + Layout.row: 3 + Layout.column: 1 + } + + // 5th row + RowLayout{ + spacing: 6 + Layout.maximumHeight: 30 + + Layout.row: 4 + Layout.column: 0 + + Item{ + Layout.fillHeight: true + + Layout.maximumWidth: 20 + Layout.preferredWidth: 20 + Layout.minimumWidth: 20 + } + + Label{ + Layout.maximumHeight: 27 + Layout.preferredHeight: 27 + Layout.minimumHeight: 27 + + Layout.maximumWidth: 260 + Layout.preferredWidth: 260 + Layout.minimumWidth: 260 + + text: qsTr("TURN Address") + + font.pointSize: 10 + font.kerning: true + + horizontalAlignment: Text.AlignLeft + verticalAlignment: Text.AlignVCenter + } + } + + Item{ + Layout.fillHeight: true + + Layout.maximumWidth: 20 + Layout.preferredWidth: 20 + Layout.minimumWidth: 20 + + Layout.row: 4 + Layout.column: 1 + } + + + InfoLineEdit { + id: lineEditTurnAddressSIP + + Layout.alignment: Qt.AlignCenter + + fieldLayoutWidth: 250 + fieldLayoutHeight: 29 + + font.pointSize: 10 + font.kerning: true + + horizontalAlignment: Text.AlignLeft + verticalAlignment: Text.AlignVCenter + + Layout.row: 4 + Layout.column: 2 + + onEditingFinished: { + ClientWrapper.settingsAdaptor.setTURNAddress(text) + } + } + + // 6th row + RowLayout{ + spacing: 6 + Layout.maximumHeight: 30 + + Layout.row: 5 + Layout.column: 0 + + Item{ + Layout.fillHeight: true + + Layout.maximumWidth: 20 + Layout.preferredWidth: 20 + Layout.minimumWidth: 20 + } + + Label{ + Layout.maximumHeight: 27 + Layout.preferredHeight: 27 + Layout.minimumHeight: 27 + + Layout.maximumWidth: 260 + Layout.preferredWidth: 260 + Layout.minimumWidth: 260 + + text: qsTr("TURN Username") + + font.pointSize: 10 + font.kerning: true + + horizontalAlignment: Text.AlignLeft + verticalAlignment: Text.AlignVCenter + } + } + + Item{ + Layout.fillHeight: true + + Layout.maximumWidth: 20 + Layout.preferredWidth: 20 + Layout.minimumWidth: 20 + + Layout.row: 5 + Layout.column: 1 + } + + InfoLineEdit { + id: lineEditTurnUsernameSIP + + Layout.alignment: Qt.AlignCenter + + fieldLayoutWidth: 250 + fieldLayoutHeight: 29 + + font.pointSize: 10 + font.kerning: true + + horizontalAlignment: Text.AlignLeft + verticalAlignment: Text.AlignVCenter + + Layout.row: 5 + Layout.column: 2 + + onEditingFinished: { + ClientWrapper.settingsAdaptor.setTURNUsername(text) + } + } + + // 7th row + RowLayout{ + spacing: 6 + Layout.maximumHeight: 30 + + Layout.row: 6 + Layout.column: 0 + + Item{ + Layout.fillHeight: true + + Layout.maximumWidth: 20 + Layout.preferredWidth: 20 + Layout.minimumWidth: 20 + } + + Label{ + Layout.maximumHeight: 27 + Layout.preferredHeight: 27 + Layout.minimumHeight: 27 + + Layout.maximumWidth: 260 + Layout.preferredWidth: 260 + Layout.minimumWidth: 260 + + text: qsTr("TURN Password") + + font.pointSize: 10 + font.kerning: true + + horizontalAlignment: Text.AlignLeft + verticalAlignment: Text.AlignVCenter + } + } + + Item{ + Layout.fillHeight: true + + Layout.maximumWidth: 20 + Layout.preferredWidth: 20 + Layout.minimumWidth: 20 + + Layout.row: 6 + Layout.column: 1 + } + + InfoLineEdit { + id: lineEditTurnPsswdSIP + + Layout.alignment: Qt.AlignCenter + + fieldLayoutWidth: 250 + fieldLayoutHeight: 29 + + font.pointSize: 10 + font.kerning: true + + horizontalAlignment: Text.AlignLeft + verticalAlignment: Text.AlignVCenter + + Layout.row: 6 + Layout.column: 2 + + echoMode: TextInput.Password + + onEditingFinished: { + ClientWrapper.settingsAdaptor.setTURNPassword(text) + } + } + + // 8th row + RowLayout{ + spacing: 6 + Layout.maximumHeight: 30 + + Layout.row: 7 + Layout.column: 0 + + Item{ + Layout.fillHeight: true + + Layout.maximumWidth: 20 + Layout.preferredWidth: 20 + Layout.minimumWidth: 20 + } + + Label{ + Layout.maximumHeight: 27 + Layout.preferredHeight: 27 + Layout.minimumHeight: 27 + + Layout.maximumWidth: 260 + Layout.preferredWidth: 260 + Layout.minimumWidth: 260 + + text: qsTr("TURN Realm") + + font.pointSize: 10 + font.kerning: true + + horizontalAlignment: Text.AlignLeft + verticalAlignment: Text.AlignVCenter + } + } + + Item{ + Layout.fillHeight: true + + Layout.maximumWidth: 20 + Layout.preferredWidth: 20 + Layout.minimumWidth: 20 + + Layout.row: 7 + Layout.column: 1 + } + + InfoLineEdit { + id: lineEditTurnRealmSIP + + Layout.alignment: Qt.AlignCenter + + fieldLayoutWidth: 250 + fieldLayoutHeight: 29 + + font.pointSize: 10 + font.kerning: true + + horizontalAlignment: Text.AlignLeft + verticalAlignment: Text.AlignVCenter + + Layout.row: 7 + Layout.column: 2 + + onEditingFinished: { + ClientWrapper.settingsAdaptor.setTURNRealm(text) + } + } + + // 9th row + ToggleSwitch{ + id: checkBoxSTUNEnableSIP + + labelText: qsTr("Use STUN") + fontPointSize: 10 + + Layout.row: 8 + Layout.column: 0 + + onSwitchToggled: { + ClientWrapper.settingsAdaptor.setUseSTUN(checked) + lineEditSTUNAddressSIP.enabled = checked + } + } + + Item{ + Layout.fillHeight: true + + Layout.maximumWidth: 20 + Layout.preferredWidth: 20 + Layout.minimumWidth: 20 + + Layout.row: 8 + Layout.column: 1 + } + + InfoLineEdit { + id: lineEditSTUNAddressSIP + + Layout.alignment: Qt.AlignCenter + + fieldLayoutWidth: 250 + fieldLayoutHeight: 29 + + font.pointSize: 10 + font.kerning: true + + horizontalAlignment: Text.AlignLeft + verticalAlignment: Text.AlignVCenter + + Layout.row: 8 + Layout.column: 2 + + onEditingFinished: { + ClientWrapper.settingsAdaptor.setSTUNAddress(text) + } + } + } + } + + Item{ + Layout.fillWidth: true + + Layout.maximumHeight: 20 + Layout.preferredHeight: 20 + Layout.minimumHeight: 20 + } + + // public address section + ColumnLayout{ + spacing: 6 + Layout.fillWidth: true + + Label { + Layout.fillWidth: true + + Layout.minimumHeight: 27 + Layout.preferredHeight: 27 + Layout.maximumHeight: 27 + + text: qsTr("Public Address") + + font.pointSize: 13 + font.kerning: true + + horizontalAlignment: Text.AlignLeft + verticalAlignment: Text.AlignVCenter + } + + Item { + Layout.fillWidth: true + + Layout.maximumHeight: 10 + Layout.preferredHeight: 10 + Layout.minimumHeight: 10 + } + + GridLayout{ + Layout.leftMargin: 20 + Layout.fillWidth: true + + rowSpacing: 6 + columnSpacing: 6 + + rows: 3 + columns: 3 + + // 1st row + ToggleSwitch{ + id: checkBoxCustomAddressPort + + Layout.maximumWidth: 88 + labelText: qsTr("Use Custom Address/Port") + fontPointSize: 10 + + Layout.row: 0 + Layout.column: 0 + + onSwitchToggled: { + ClientWrapper.settingsAdaptor.setUseCustomAddressAndPort(checked) + lineEditSIPCustomAddress.enabled = checked + customPortSIPSpinBox.enabled = checked + } + } + + Item{ + Layout.fillHeight: true + Layout.fillWidth: true + + Layout.row: 0 + Layout.column: 1 + } + + //2nd row + Label{ + Layout.leftMargin: 26 + + Layout.maximumHeight: 27 + Layout.preferredHeight: 27 + Layout.minimumHeight: 27 + + Layout.maximumWidth: 60 + Layout.preferredWidth: 60 + Layout.minimumWidth: 60 + + text: qsTr("Address") + font.pointSize: 10 + font.kerning: true + + horizontalAlignment: Text.AlignLeft + verticalAlignment: Text.AlignVCenter + + Layout.row: 1 + Layout.column: 0 + } + + Item{ + Layout.fillHeight: true + Layout.fillWidth: true + + Layout.row: 1 + Layout.column: 1 + } + + InfoLineEdit { + id: lineEditSIPCustomAddress + + Layout.alignment: Qt.AlignCenter + + fieldLayoutWidth: 250 + fieldLayoutHeight: 29 + + font.pointSize: 10 + font.kerning: true + + horizontalAlignment: Text.AlignLeft + verticalAlignment: Text.AlignVCenter + + Layout.row: 1 + Layout.column: 2 + + onEditingFinished: { + ClientWrapper.settingsAdaptor.lineEditSIPCustomAddressLineEditTextChanged(text) + } + } + + //3rd row + Label{ + Layout.leftMargin: 26 + + Layout.maximumHeight: 27 + Layout.preferredHeight: 27 + Layout.minimumHeight: 27 + + Layout.maximumWidth: 60 + Layout.preferredWidth: 60 + Layout.minimumWidth: 60 + + text: qsTr("Port") + font.pointSize: 10 + font.kerning: true + + horizontalAlignment: Text.AlignLeft + verticalAlignment: Text.AlignVCenter + + Layout.row: 2 + Layout.column: 0 + } + + Item{ + Layout.fillHeight: true + Layout.fillWidth: true + + Layout.row: 2 + Layout.column: 1 + } + + SpinBox{ + id: customPortSIPSpinBox + + Layout.maximumWidth: 250 + Layout.preferredWidth: 250 + Layout.minimumWidth: 250 + + Layout.maximumHeight: 30 + Layout.minimumHeight: 30 + Layout.preferredHeight: 30 + + Layout.alignment: Qt.AlignCenter + + font.pointSize: 10 + font.kerning: true + + from: 0 + to: 65535 + stepSize: 1 + + Layout.row: 2 + Layout.column: 2 + + onValueModified: { + ClientWrapper.settingsAdaptor.customPortSIPSpinBoxValueChanged(value) + } + } + } + } + + // media section + ColumnLayout{ + spacing: 6 + Layout.fillWidth: true + + Label { + Layout.fillWidth: true + + Layout.minimumHeight: 27 + Layout.preferredHeight: 27 + Layout.maximumHeight: 27 + + text: qsTr("Media") + + font.pointSize: 13 + font.kerning: true + + horizontalAlignment: Text.AlignLeft + verticalAlignment: Text.AlignVCenter + } + + Item { + Layout.fillWidth: true + + Layout.maximumHeight: 10 + Layout.preferredHeight: 10 + Layout.minimumHeight: 10 + } + + ColumnLayout { + spacing: 6 + Layout.fillWidth: true + + ToggleSwitch { + id: videoCheckBoxSIP + + Layout.leftMargin: 20 + + labelText: qsTr("Enable Video") + fontPointSize: 10 + + onSwitchToggled: { + ClientWrapper.settingsAdaptor.setVideoState(checked) + } + } + + RowLayout { + spacing: 6 + Layout.fillWidth: true + Layout.leftMargin: 20 + + ColumnLayout { + spacing: 6 + Layout.maximumWidth: 348 + + RowLayout { + spacing: 6 + Layout.fillWidth: true + + Layout.maximumHeight: 30 + + Label { + Layout.fillWidth: true + + Layout.minimumHeight: 30 + Layout.preferredHeight: 30 + Layout.maximumHeight: 30 + + text: qsTr("Video Codecs") + font.pointSize: 10 + font.kerning: true + + horizontalAlignment: Text.AlignLeft + verticalAlignment: Text.AlignVCenter + } + + Item { + Layout.fillHeight: true + + Layout.minimumWidth: 20 + Layout.preferredWidth: 20 + Layout.maximumWidth: 20 + } + + HoverableRadiusButton { + id: videoDownPushButtonSIP + + Layout.minimumWidth: 30 + Layout.preferredWidth: 30 + Layout.maximumWidth: 30 + + Layout.minimumHeight: 30 + Layout.preferredHeight: 30 + Layout.maximumHeight: 30 + + radius: height / 2 + scale: 1 + + buttonImageHeight: height + buttonImageWidth: height + + font.pointSize: 9 + font.kerning: true + + icon.source: "qrc:/images/icons/round-arrow_drop_down-24px.svg" + icon.width: 32 + icon.height: 32 + + onClicked: { + decreaseVideoCodecPriority() + } + } + + HoverableRadiusButton { + id: videoUpPushButtonSIP + + Layout.minimumWidth: 30 + Layout.preferredWidth: 30 + Layout.maximumWidth: 30 + + Layout.minimumHeight: 30 + Layout.preferredHeight: 30 + Layout.maximumHeight: 30 + + radius: height / 2 + + buttonImageHeight: height + buttonImageWidth: height + + font.pointSize: 9 + font.kerning: true + + icon.source: "qrc:/images/icons/round-arrow_drop_up-24px.svg" + icon.width: 32 + icon.height: 32 + + onClicked: { + increaseVideoCodecPriority() + } + } + } + + ListViewJami { + id: videoListWidgetSIP + + Layout.minimumWidth: 348 + Layout.preferredWidth: 348 + Layout.maximumWidth: 348 + + Layout.minimumHeight: 192 + Layout.preferredHeight: 192 + Layout.maximumHeight: 192 + + model: videoCodecListModelSIP + + delegate: VideoCodecDelegate { + id: videoCodecDelegate + + width: videoListWidgetSIP.width + height: videoListWidgetSIP.height / 4 + + videoCodecName : VideoCodecName + isEnabled : IsEnabled + videoCodecId: VideoCodecID + + onClicked: { + videoListWidgetSIP.currentIndex = index + } + + onVideoCodecStateChange:{ + ClientWrapper.settingsAdaptor.videoCodecsStateChange(idToSet , isToBeEnabled) + updateVideoCodecs() + } + } + } + } + + ColumnLayout { + spacing: 6 + Layout.maximumWidth: 348 + + RowLayout { + spacing: 6 + Layout.fillWidth: true + + Layout.maximumHeight: 30 + + Label { + Layout.fillWidth: true + + Layout.minimumHeight: 30 + Layout.preferredHeight: 30 + Layout.maximumHeight: 30 + + text: qsTr("Audio Codecs") + font.pointSize: 10 + font.kerning: true + + horizontalAlignment: Text.AlignLeft + verticalAlignment: Text.AlignVCenter + } + + Item { + Layout.fillHeight: true + + Layout.minimumWidth: 20 + Layout.preferredWidth: 20 + Layout.maximumWidth: 20 + } + + HoverableRadiusButton { + id: audioDownPushButtonSIP + + Layout.minimumWidth: 30 + Layout.preferredWidth: 30 + Layout.maximumWidth: 30 + + Layout.minimumHeight: 30 + Layout.preferredHeight: 30 + Layout.maximumHeight: 30 + + radius: height / 2 + + buttonImageHeight: height + buttonImageWidth: height + + font.pointSize: 9 + font.kerning: true + + icon.source: "qrc:/images/icons/round-arrow_drop_down-24px.svg" + icon.width: 32 + icon.height: 32 + + onClicked: { + decreaseAudioCodecPriority() + } + } + + HoverableRadiusButton { + id: audioUpPushButtonSIP + + Layout.minimumWidth: 30 + Layout.preferredWidth: 30 + Layout.maximumWidth: 30 + + Layout.minimumHeight: 30 + Layout.preferredHeight: 30 + Layout.maximumHeight: 30 + + radius: height / 2 + + buttonImageHeight: height + buttonImageWidth: height + + font.pointSize: 9 + font.kerning: true + + icon.source: "qrc:/images/icons/round-arrow_drop_up-24px.svg" + icon.width: 32 + icon.height: 32 + + onClicked: { + increaseAudioCodecPriority() + } + } + } + + ListViewJami { + id: audioListWidgetSIP + + Layout.minimumWidth: 348 + Layout.preferredWidth: 348 + Layout.maximumWidth: 348 + + Layout.minimumHeight: 192 + Layout.preferredHeight: 192 + Layout.maximumHeight: 192 + + model: audioCodecListModelSIP + + delegate: AudioCodecDelegate { + id: audioCodecDelegate + + width: audioListWidgetSIP.width + height: audioListWidgetSIP.height / 4 + + layer.mipmap: false + clip: true + + audioCodecName : AudioCodecName + isEnabled : IsEnabled + audioCodecId: AudioCodecID + samplerRate: Samplerate + + onClicked: { + audioListWidgetSIP.currentIndex = index + } + + onAudioCodecStateChange:{ + ClientWrapper.settingsAdaptor.audioCodecsStateChange(idToSet , isToBeEnabled) + updateAudioCodecs() + } + } + } + } + } + } + + } + + Item { + Layout.fillWidth: true + + Layout.maximumHeight: 20 + Layout.preferredHeight: 20 + Layout.minimumHeight: 20 + } + + ColumnLayout{ + spacing: 6 + Layout.fillWidth: true + + Label { + Layout.fillWidth: true + + Layout.minimumHeight: 27 + Layout.preferredHeight: 27 + Layout.maximumHeight: 27 + + text: qsTr("SDP Session Negotiation(ICE Fallback)") + + font.pointSize: 13 + font.kerning: true + + horizontalAlignment: Text.AlignLeft + verticalAlignment: Text.AlignVCenter + } + + Label { + Layout.fillWidth: true + + Layout.minimumHeight: 21 + Layout.preferredHeight: 21 + Layout.maximumHeight: 21 + + text: qsTr("Only used during negotiation in case ICE is not supported") + + font.pointSize: 10 + font.kerning: true + + horizontalAlignment: Text.AlignLeft + verticalAlignment: Text.AlignVCenter + } + + Item { + Layout.fillWidth: true + + Layout.maximumHeight: 10 + Layout.preferredHeight: 10 + Layout.minimumHeight: 10 + } + + GridLayout{ + Layout.leftMargin: 20 + Layout.fillWidth: true + + rowSpacing: 6 + columnSpacing: 6 + + rows: 4 + columns: 3 + + // 1st row + Label{ + Layout.minimumWidth: 162 + Layout.preferredWidth: 162 + Layout.maximumWidth: 162 + + Layout.minimumHeight: 28 + Layout.preferredHeight: 28 + Layout.maximumHeight: 28 + + text: qsTr("Audio RTP Min Port") + font.pointSize: 10 + font.kerning: true + + horizontalAlignment: Text.AlignLeft + verticalAlignment: Text.AlignVCenter + + Layout.row: 0 + Layout.column: 0 + } + + Item{ + Layout.fillHeight: true + Layout.fillWidth: true + + Layout.row: 0 + Layout.column: 1 + } + + SpinBox{ + id:audioRTPMinPortSpinBox + + Layout.minimumWidth: 250 + Layout.preferredWidth: 250 + Layout.maximumWidth: 250 + + Layout.minimumHeight: 30 + Layout.preferredHeight: 30 + Layout.maximumHeight: 30 + + font.pointSize: 10 + font.kerning: true + + from: 0 + to: 65535 + stepSize: 1 + + Layout.row: 0 + Layout.column: 2 + + onValueModified: { + audioRTPMinPortSpinBoxEditFinished(value) + } + } + + // 2nd row + Label{ + Layout.minimumWidth: 162 + Layout.preferredWidth: 162 + Layout.maximumWidth: 162 + + Layout.minimumHeight: 28 + Layout.preferredHeight: 28 + Layout.maximumHeight: 28 + + text: qsTr("Audio RTP Max Port") + font.pointSize: 10 + font.kerning: true + + horizontalAlignment: Text.AlignLeft + verticalAlignment: Text.AlignVCenter + + Layout.row: 1 + Layout.column: 0 + } + + Item{ + Layout.fillHeight: true + Layout.fillWidth: true + + Layout.row: 1 + Layout.column: 1 + } + + SpinBox{ + id:audioRTPMaxPortSpinBox + + Layout.minimumWidth: 250 + Layout.preferredWidth: 250 + Layout.maximumWidth: 250 + + Layout.minimumHeight: 30 + Layout.preferredHeight: 30 + Layout.maximumHeight: 30 + + font.pointSize: 10 + font.kerning: true + + from: 0 + to: 65535 + stepSize: 1 + + Layout.row: 1 + Layout.column: 2 + + onValueModified: { + audioRTPMaxPortSpinBoxEditFinished(value) + } + } + + // 3rd row + Label{ + Layout.minimumWidth: 162 + Layout.preferredWidth: 162 + Layout.maximumWidth: 162 + + Layout.minimumHeight: 28 + Layout.preferredHeight: 28 + Layout.maximumHeight: 28 + + text: qsTr("Video RTP Min Port") + font.pointSize: 10 + font.kerning: true + + horizontalAlignment: Text.AlignLeft + verticalAlignment: Text.AlignVCenter + + Layout.row: 2 + Layout.column: 0 + } + + Item{ + Layout.fillHeight: true + Layout.fillWidth: true + + Layout.row: 2 + Layout.column: 1 + } + + SpinBox{ + id:videoRTPMinPortSpinBox + + Layout.minimumWidth: 250 + Layout.preferredWidth: 250 + Layout.maximumWidth: 250 + + Layout.minimumHeight: 30 + Layout.preferredHeight: 30 + Layout.maximumHeight: 30 + + font.pointSize: 10 + font.kerning: true + + from: 0 + to: 65535 + stepSize: 1 + + Layout.row: 2 + Layout.column: 2 + + onValueModified: { + videoRTPMinPortSpinBoxEditFinished(value) + } + } + + // 4th row + Label{ + Layout.minimumWidth: 162 + Layout.preferredWidth: 162 + Layout.maximumWidth: 162 + + Layout.minimumHeight: 28 + Layout.preferredHeight: 28 + Layout.maximumHeight: 28 + + text: qsTr("Video RTP Max Port") + font.pointSize: 10 + font.kerning: true + + horizontalAlignment: Text.AlignLeft + verticalAlignment: Text.AlignVCenter + + Layout.row: 3 + Layout.column: 0 + } + + Item{ + Layout.fillHeight: true + Layout.fillWidth: true + + Layout.row: 3 + Layout.column: 1 + } + + SpinBox{ + id:videoRTPMaxPortSpinBox + + Layout.minimumWidth: 250 + Layout.preferredWidth: 250 + Layout.maximumWidth: 250 + + Layout.minimumHeight: 30 + Layout.preferredHeight: 30 + Layout.maximumHeight: 30 + + font.pointSize: 10 + font.kerning: true + + from: 0 + to: 65535 + stepSize: 1 + + Layout.row: 3 + Layout.column: 2 + + onValueModified: { + videoRTPMaxPortSpinBoxEditFinished(value) + } + } + } + } + + // spacers + Item { + Layout.fillWidth: true + + Layout.maximumHeight: 48 + Layout.preferredHeight: 48 + Layout.minimumHeight: 48 + } + + Item { + Layout.fillHeight: true + Layout.fillWidth: true + } +} + + diff --git a/src/settingsview/components/AdvancedSettingsView.qml b/src/settingsview/components/AdvancedSettingsView.qml new file mode 100644 index 00000000..003869b9 --- /dev/null +++ b/src/settingsview/components/AdvancedSettingsView.qml @@ -0,0 +1,1370 @@ +/* + * Copyright (C) 2019-2020 by Savoir-faire Linux + * Author: Yang Wang + * + * 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 . + */ + +import QtQuick 2.15 +import QtQuick.Window 2.14 +import QtQuick.Controls 2.14 +import QtQuick.Controls.Universal 2.12 +import QtQuick.Layouts 1.3 +import QtGraphicalEffects 1.14 +import QtQuick.Controls.Styles 1.4 +import QtQuick.Dialogs 1.3 +import Qt.labs.platform 1.1 +import net.jami.Models 1.0 + +import "../../commoncomponents" + +ColumnLayout { + function updateAccountInfoDisplayedAdvance() { + //Call Settings + checkAutoConnectOnLocalNetwork.checked = ClientWrapper.settingsAdaptor.getAccountConfig_PeerDiscovery() + checkBoxUntrusted.checked = ClientWrapper.settingsAdaptor.getAccountConfig_DHT_PublicInCalls() + checkBoxAutoAnswer.checked = ClientWrapper.settingsAdaptor.getAccountConfig_AutoAnswer() + checkBoxCustomRingtone.checked = ClientWrapper.settingsAdaptor.getAccountConfig_Ringtone_RingtoneEnabled() + + // Name Server + lineEditNameServer.text = ClientWrapper.settingsAdaptor.getAccountConfig_RingNS_Uri() + + //OpenDHT Config + checkBoxEnableProxy.checked = ClientWrapper.settingsAdaptor.getAccountConfig_ProxyEnabled() + lineEditProxy.text = ClientWrapper.settingsAdaptor.getAccountConfig_ProxyServer() + lineEditBootstrap.text = ClientWrapper.settingsAdaptor.getAccountConfig_Hostname() + + // Security + btnCACert.text = ClientWrapper.utilsAdaptor.toFileInfoName(ClientWrapper.settingsAdaptor.getAccountConfig_TLS_CertificateListFile()) + btnUserCert.text = ClientWrapper.utilsAdaptor.toFileInfoName(ClientWrapper.settingsAdaptor.getAccountConfig_TLS_CertificateFile()) + btnPrivateKey.text = ClientWrapper.utilsAdaptor.toFileInfoName(ClientWrapper.settingsAdaptor.getAccountConfig_TLS_PrivateKeyFile()) + + // Connectivity + checkBoxUPnP.checked = ClientWrapper.settingsAdaptor.getAccountConfig_UpnpEnabled() + checkBoxTurnEnable.checked = ClientWrapper.settingsAdaptor.getAccountConfig_TURN_Enabled() + lineEditTurnAddress.text = ClientWrapper.settingsAdaptor.getAccountConfig_TURN_Server() + lineEditTurnUsername.text = ClientWrapper.settingsAdaptor.getAccountConfig_TURN_Username() + lineEditTurnPassword.text = ClientWrapper.settingsAdaptor.getAccountConfig_TURN_Password() + checkBoxSTUNEnable.checked = ClientWrapper.settingsAdaptor.getAccountConfig_STUN_Enabled() + lineEditSTUNAddress.text = ClientWrapper.settingsAdaptor.getAccountConfig_STUN_Server() + // codecs + videoCheckBox.checked = ClientWrapper.settingsAdaptor.getAccountConfig_Video_Enabled() + // update audio and video codec, make sure this change does not trigger item change events + updateAudioCodecs(); + updateVideoCodecs(); + btnRingtone.enabled = ClientWrapper.settingsAdaptor.getAccountConfig_Ringtone_RingtoneEnabled() + btnRingtone.text = ClientWrapper.utilsAdaptor.toFileInfoName(ClientWrapper.settingsAdaptor.getAccountConfig_Ringtone_RingtonePath()) + lineEditProxy.enabled = ClientWrapper.settingsAdaptor.getAccountConfig_ProxyEnabled() + lineEditSTUNAddress.enabled = ClientWrapper.settingsAdaptor.getAccountConfig_STUN_Enabled() + } + + function updateAudioCodecs(){ + audioCodecListModel.layoutAboutToBeChanged() + audioCodecListModel.dataChanged(audioCodecListModel.index(0, 0), + audioCodecListModel.index(audioCodecListModel.rowCount() - 1, 0)) + audioCodecListModel.layoutChanged() + } + + function updateVideoCodecs(){ + videoCodecListModel.layoutAboutToBeChanged() + videoCodecListModel.dataChanged(videoCodecListModel.index(0, 0), + videoCodecListModel.index(videoCodecListModel.rowCount() - 1, 0)) + videoCodecListModel.layoutChanged() + } + + function decreaseAudioCodecPriority(){ + var index = audioListWidget.currentIndex + var codecId = audioCodecListModel.data(audioCodecListModel.index(index,0), AudioCodecListModel.AudioCodecID) + + ClientWrapper.settingsAdaptor.decreaseAudioCodecPriority(codecId) + audioListWidget.currentIndex = index + 1 + updateAudioCodecs() + } + + function increaseAudioCodecPriority(){ + var index = audioListWidget.currentIndex + var codecId = audioCodecListModel.data(audioCodecListModel.index(index,0), AudioCodecListModel.AudioCodecID) + + ClientWrapper.settingsAdaptor.increaseAudioCodecPriority(codecId) + audioListWidget.currentIndex = index - 1 + updateAudioCodecs() + } + + function decreaseVideoCodecPriority(){ + var index = videoListWidget.currentIndex + var codecId = videoCodecListModel.data(videoCodecListModel.index(index,0), VideoCodecListModel.VideoCodecID) + + ClientWrapper.settingsAdaptor.decreaseVideoCodecPriority(codecId) + videoListWidget.currentIndex = index + 1 + updateVideoCodecs() + } + + function increaseVideoCodecPriority(){ + var index = videoListWidget.currentIndex + var codecId = videoCodecListModel.data(videoCodecListModel.index(index,0), VideoCodecListModel.VideoCodecID) + + ClientWrapper.settingsAdaptor.increaseVideoCodecPriority(codecId) + videoListWidget.currentIndex = index - 1 + updateVideoCodecs() + } + + VideoCodecListModel{ + id: videoCodecListModel + } + + AudioCodecListModel{ + id: audioCodecListModel + } + + function changeRingtonePath(url){ + if(url.length !== 0) { + ClientWrapper.settingsAdaptor.set_RingtonePath(url) + btnRingtone.text = ClientWrapper.utilsAdaptor.toFileInfoName(ClientWrapper.settingsAdaptor.getAccountConfig_Ringtone_RingtonePath()) + } else if (ClientWrapper.settingsAdaptor.getAccountConfig_Ringtone_RingtonePath().length === 0){ + btnRingtone.text = qsTr("Add a custom ringtone") + } + } + + function changeFileCACert(url){ + if(url.length !== 0) { + ClientWrapper.settingsAdaptor.set_FileCACert(url) + btnCACert.text = ClientWrapper.utilsAdaptor.toFileInfoName(ClientWrapper.settingsAdaptor.getAccountConfig_TLS_CertificateListFile()) + } + } + + function changeFileUserCert(url){ + if(url.length !== 0) { + ClientWrapper.settingsAdaptor.set_FileUserCert(url) + btnUserCert.text = ClientWrapper.utilsAdaptor.toFileInfoName(ClientWrapper.settingsAdaptor.getAccountConfig_TLS_CertificateFile()) + } + } + + function changeFilePrivateKey(url){ + if(url.length !== 0) { + ClientWrapper.settingsAdaptor.set_FilePrivateKey(url) + btnPrivateKey.text = ClientWrapper.utilsAdaptor.toFileInfoName(ClientWrapper.settingsAdaptor.getAccountConfig_TLS_PrivateKeyFile()) + } + } + + JamiFileDialog { + id: ringtonePath_Dialog + + property string oldPath : ClientWrapper.settingsAdaptor.getAccountConfig_Ringtone_RingtonePath() + property string openPath : oldPath === "" ? (ClientWrapper.utilsAdaptor.getCurrentPath() + "/ringtones/") : (ClientWrapper.utilsAdaptor.toFileAbsolutepath(oldPath)) + + mode: JamiFileDialog.OpenFile + title: qsTr("Select a new ringtone") + folder: openPath + + nameFilters: [qsTr("Audio Files") + " (*.wav *.ogg *.opus *.mp3 *.aiff *.wma)", qsTr( + "All files") + " (*)"] + + onRejected: {} + + onVisibleChanged: { + if (!visible) { + rejected() + } + } + + onAccepted: { + var url = ClientWrapper.utilsAdaptor.getAbsPath(file.toString()) + changeRingtonePath(url) + } + } + + JamiFileDialog { + id: caCert_Dialog + + property string oldPath : ClientWrapper.settingsAdaptor.getAccountConfig_TLS_CertificateListFile() + property string openPath : oldPath === "" ? (ClientWrapper.utilsAdaptor.getCurrentPath() + "/ringtones/") : (ClientWrapper.utilsAdaptor.toFileAbsolutepath(oldPath)) + + mode: JamiFileDialog.OpenFile + title: qsTr("Select a CA certificate") + folder: openPath + nameFilters: [qsTr("Certificate File") + " (*.crt)", qsTr( + "All files") + " (*)"] + + onRejected: {} + + onVisibleChanged: { + if (!visible) { + rejected() + } + } + + onAccepted: { + var url = ClientWrapper.utilsAdaptor.getAbsPath(file.toString()) + changeFileCACert(url) + } + } + + JamiFileDialog { + id: userCert_Dialog + + property string oldPath : ClientWrapper.settingsAdaptor.getAccountConfig_TLS_CertificateFile() + property string openPath : oldPath === "" ? (ClientWrapper.utilsAdaptor.getCurrentPath() + "/ringtones/") : (ClientWrapper.utilsAdaptor.toFileAbsolutepath(oldPath)) + + mode: JamiFileDialog.OpenFile + title: qsTr("Select a user certificate") + folder: openPath + nameFilters: [qsTr("Certificate File") + " (*.crt)", qsTr( + "All files") + " (*)"] + + onRejected: {} + + onVisibleChanged: { + if (!visible) { + rejected() + } + } + + onAccepted: { + var url = ClientWrapper.utilsAdaptor.getAbsPath(file.toString()) + changeFileUserCert(url) + } + } + + JamiFileDialog { + id: privateKey_Dialog + + property string oldPath : ClientWrapper.settingsAdaptor.getAccountConfig_TLS_PrivateKeyFile() + property string openPath : oldPath === "" ? (ClientWrapper.utilsAdaptor.getCurrentPath() + "/ringtones/") : (ClientWrapper.utilsAdaptor.toFileAbsolutepath(oldPath)) + + mode: JamiFileDialog.OpenFile + title: qsTr("Select a private key") + folder: openPath + nameFilters: [qsTr("Key File") + " (*.key)", qsTr( + "All files") + " (*)"] + + onRejected: {} + + onVisibleChanged: { + if (!visible) { + rejected() + } + } + + onAccepted: { + var url = ClientWrapper.utilsAdaptor.getAbsPath(file.toString()) + changeFilePrivateKey(url) + } + } + + spacing: 6 + + Layout.preferredWidth: 532 + Layout.maximumWidth: 532 + + Item { + Layout.fillWidth: true + + Layout.minimumHeight: 24 + Layout.preferredHeight: 24 + Layout.maximumHeight: 24 + } + + ColumnLayout { + spacing: 6 + Layout.fillWidth: true + + Label { + Layout.fillWidth: true + + Layout.minimumHeight: 27 + Layout.preferredHeight: 27 + Layout.maximumHeight: 27 + + text: qsTr("Call Settings") + font.pointSize: 13 + font.kerning: true + + horizontalAlignment: Text.AlignLeft + verticalAlignment: Text.AlignVCenter + } + + Item { + Layout.fillWidth: true + + Layout.minimumHeight: 10 + Layout.preferredHeight: 10 + Layout.maximumHeight: 10 + } + + ColumnLayout { + spacing: 6 + Layout.fillWidth: true + + ToggleSwitch { + id: checkBoxUntrusted + + Layout.leftMargin: 20 + + labelText: qsTr("Allow incoming calls from unknown contacts") + fontPointSize: 10 + + onSwitchToggled: { + ClientWrapper.settingsAdaptor.setCallsUntrusted(checked) + } + } + + ToggleSwitch { + id: checkBoxAutoAnswer + + Layout.fillWidth: true + Layout.leftMargin: 20 + + labelText: qsTr("Auto Answer Calls") + fontPointSize: 10 + + onSwitchToggled: { + ClientWrapper.settingsAdaptor.setAutoAnswerCalls(checked) + } + } + + RowLayout { + spacing: 6 + Layout.fillWidth: true + Layout.leftMargin: 20 + Layout.maximumHeight: 30 + + ToggleSwitch { + id: checkBoxCustomRingtone + + labelText: qsTr("Enable Custom Ringtone") + fontPointSize: 10 + + onSwitchToggled: { + ClientWrapper.settingsAdaptor.setEnableRingtone(checked) + btnRingtone.enabled = checked + } + } + + HoverableRadiusButton { + id: btnRingtone + + Layout.minimumWidth: 300 + Layout.preferredWidth: 300 + Layout.maximumWidth: 300 + + Layout.minimumHeight: 30 + Layout.preferredHeight: 30 + Layout.maximumHeight: 30 + + radius: height / 2 + + icon.source: "qrc:/images/icons/round-folder-24px.svg" + icon.width: 16 + icon.height: 16 + + onClicked: { + ringtonePath_Dialog.open() + } + } + } + } + } + + Item { + Layout.fillWidth: true + + Layout.minimumHeight: 20 + Layout.preferredHeight: 20 + Layout.maximumHeight: 20 + } + + ColumnLayout { + spacing: 6 + Layout.fillWidth: true + + Label { + Layout.fillWidth: true + + Layout.minimumHeight: 27 + Layout.preferredHeight: 27 + Layout.maximumHeight: 27 + + text: qsTr("Name Server") + font.pointSize: 13 + font.kerning: true + + horizontalAlignment: Text.AlignLeft + verticalAlignment: Text.AlignVCenter + } + + Item { + Layout.fillWidth: true + + Layout.minimumHeight: 10 + Layout.preferredHeight: 10 + Layout.maximumHeight: 10 + } + + RowLayout { + Layout.fillWidth: true + Layout.leftMargin: 20 + Layout.maximumHeight: 29 + + Label { + Layout.minimumWidth: 60 + + Layout.minimumHeight: 29 + Layout.preferredHeight: 29 + Layout.maximumHeight: 29 + + text: qsTr("Address") + + font.pointSize: 10 + font.kerning: true + + horizontalAlignment: Text.AlignLeft + verticalAlignment: Text.AlignVCenter + } + + Item { + Layout.fillHeight: true + Layout.fillWidth: true + } + + InfoLineEdit { + id: lineEditNameServer + + fieldLayoutWidth: 300 + fieldLayoutHeight: 29 + + font.pointSize: 10 + font.kerning: true + + horizontalAlignment: Text.AlignLeft + verticalAlignment: Text.AlignVCenter + + onEditingFinished: { + ClientWrapper.settingsAdaptor.setNameServer(text) + } + } + } + } + + Item { + Layout.fillWidth: true + + Layout.minimumHeight: 20 + Layout.preferredHeight: 20 + Layout.maximumHeight: 20 + } + + ColumnLayout { + spacing: 6 + Layout.fillWidth: true + + Label { + Layout.fillWidth: true + + Layout.minimumHeight: 27 + Layout.preferredHeight: 27 + Layout.maximumHeight: 27 + + text: qsTr("OpenDHT Configuration") + font.pointSize: 13 + font.kerning: true + + horizontalAlignment: Text.AlignLeft + verticalAlignment: Text.AlignVCenter + } + + Item { + Layout.fillWidth: true + + Layout.minimumHeight: 10 + Layout.preferredHeight: 10 + Layout.maximumHeight: 10 + } + + ColumnLayout { + spacing: 6 + Layout.fillWidth: true + + RowLayout { + spacing: 6 + Layout.fillWidth: true + Layout.leftMargin: 20 + + ToggleSwitch { + id: checkBoxEnableProxy + + labelText: qsTr("Enable proxy") + fontPointSize: 10 + + onSwitchToggled: { + ClientWrapper.settingsAdaptor.setEnableProxy(checked) + lineEditProxy.enabled = checked + } + } + + Item { + Layout.fillHeight: true + Layout.fillWidth: true + } + + InfoLineEdit { + id: lineEditProxy + + fieldLayoutWidth: 300 + fieldLayoutHeight: 29 + + font.pointSize: 10 + font.kerning: true + + horizontalAlignment: Text.AlignLeft + verticalAlignment: Text.AlignVCenter + + onEditingFinished: { + ClientWrapper.settingsAdaptor.setProxyAddress(text) + } + } + } + + RowLayout { + spacing: 6 + Layout.fillWidth: true + Layout.leftMargin: 20 + + Label { + id: labelBootstrap + + Layout.minimumWidth: 72 + Layout.preferredWidth: 72 + + Layout.minimumHeight: 29 + Layout.preferredHeight: 29 + Layout.maximumHeight: 29 + + text: qsTr("Bootstrap") + font.pointSize: 10 + font.kerning: true + } + + Item { + Layout.fillHeight: true + Layout.fillWidth: true + } + + InfoLineEdit { + id: lineEditBootstrap + + fieldLayoutWidth: 300 + fieldLayoutHeight: 29 + + font.pointSize: 10 + font.kerning: true + + horizontalAlignment: Text.AlignLeft + verticalAlignment: Text.AlignVCenter + + onEditingFinished: { + ClientWrapper.settingsAdaptor.setBootstrapAddress(text) + } + } + } + } + } + + ColumnLayout { + spacing: 6 + Layout.fillWidth: true + + Label { + Layout.fillWidth: true + + Layout.minimumHeight: 27 + Layout.preferredHeight: 27 + Layout.maximumHeight: 27 + + text: qsTr("Security") + font.pointSize: 13 + font.kerning: true + + horizontalAlignment: Text.AlignLeft + verticalAlignment: Text.AlignVCenter + } + + Item { + Layout.fillWidth: true + + Layout.minimumHeight: 10 + Layout.preferredHeight: 10 + Layout.maximumHeight: 10 + } + + ColumnLayout { + spacing: 6 + Layout.fillWidth: true + + GridLayout { + rows: 4 + columns: 2 + rowSpacing: 0 + columnSpacing: 6 + + Layout.fillWidth: true + Layout.leftMargin: 20 + + // CA Certificate + Label { + Layout.fillWidth: true + + Layout.minimumHeight: 32 + Layout.preferredHeight: 32 + Layout.maximumHeight: 32 + + text: qsTr("CA Certificate") + font.pointSize: 10 + font.kerning: true + + horizontalAlignment: Text.AlignLeft + verticalAlignment: Text.AlignVCenter + } + + HoverableRadiusButton { + id: btnCACert + + radius: height / 2 + + Layout.minimumWidth: 298 + Layout.preferredWidth: 298 + Layout.maximumWidth: 298 + + Layout.minimumHeight: 30 + Layout.preferredHeight: 30 + Layout.maximumHeight: 30 + + icon.source: "qrc:/images/icons/round-folder-24px.svg" + icon.width: 16 + icon.height: 16 + + onClicked: { + caCert_Dialog.open() + } + } + + // User Certificate + Label { + Layout.fillWidth: true + + Layout.minimumHeight: 32 + Layout.preferredHeight: 32 + Layout.maximumHeight: 32 + + text: qsTr("User Certificate") + font.pointSize: 10 + font.kerning: true + + horizontalAlignment: Text.AlignLeft + verticalAlignment: Text.AlignVCenter + } + + HoverableRadiusButton { + id: btnUserCert + + radius: height / 2 + + Layout.minimumWidth: 298 + Layout.preferredWidth: 298 + Layout.maximumWidth: 298 + + Layout.minimumHeight: 30 + Layout.preferredHeight: 30 + Layout.maximumHeight: 30 + + icon.source: "qrc:/images/icons/round-folder-24px.svg" + icon.width: 16 + icon.height: 16 + + onClicked: { + userCert_Dialog.open() + } + } + + // Private Key + Label { + Layout.fillWidth: true + + Layout.minimumHeight: 32 + Layout.preferredHeight: 32 + Layout.maximumHeight: 32 + + text: qsTr("Private Key") + font.pointSize: 10 + font.kerning: true + + horizontalAlignment: Text.AlignLeft + verticalAlignment: Text.AlignVCenter + } + + HoverableRadiusButton { + id: btnPrivateKey + + radius: height / 2 + + Layout.minimumWidth: 298 + Layout.preferredWidth: 298 + Layout.maximumWidth: 298 + + Layout.minimumHeight: 30 + Layout.preferredHeight: 30 + Layout.maximumHeight: 30 + + icon.source: "qrc:/images/icons/round-folder-24px.svg" + icon.width: 16 + icon.height: 16 + + onClicked: { + privateKey_Dialog.open() + } + } + + // Private key password + Label { + Layout.fillWidth: true + + Layout.minimumHeight: 29 + Layout.preferredHeight: 29 + Layout.maximumHeight: 29 + + text: qsTr("Private Key Password") + font.pointSize: 10 + font.kerning: true + + horizontalAlignment: Text.AlignLeft + verticalAlignment: Text.AlignVCenter + } + + InfoLineEdit { + id: lineEditCertPassword + + fieldLayoutWidth: 300 + fieldLayoutHeight: 29 + + font.pointSize: 10 + font.kerning: true + + horizontalAlignment: Text.AlignLeft + verticalAlignment: Text.AlignVCenter + echoMode: TextInput.Password + } + } + } + } + + Item { + Layout.fillWidth: true + + Layout.minimumHeight: 20 + Layout.preferredHeight: 20 + Layout.maximumHeight: 20 + } + + ColumnLayout { + spacing: 6 + Layout.fillWidth: true + + Label { + Layout.fillWidth: true + Layout.topMargin: 10 + + Layout.minimumHeight: 27 + Layout.preferredHeight: 27 + Layout.maximumHeight: 27 + + text: qsTr("Connectivity") + font.pointSize: 13 + font.kerning: true + + horizontalAlignment: Text.AlignLeft + verticalAlignment: Text.AlignVCenter + } + + Item { + Layout.fillWidth: true + + Layout.minimumHeight: 10 + Layout.preferredHeight: 10 + Layout.maximumHeight: 10 + } + + ColumnLayout { + spacing: 6 + Layout.fillWidth: true + + GridLayout { + Layout.leftMargin: 20 + Layout.fillWidth: true + + rows: 6 + columns: 3 + rowSpacing: 6 + columnSpacing: 6 + + // row 2 + ToggleSwitch { + id: checkAutoConnectOnLocalNetwork + + Layout.row: 0 + Layout.column: 0 + + labelText: qsTr("Auto Connect On Local Network") + fontPointSize: 10 + + onSwitchToggled: { + ClientWrapper.settingsAdaptor.setAutoConnectOnLocalNetwork(checked) + } + } + + Item { + Layout.row: 0 + Layout.column: 1 + + Layout.fillHeight: true + + Layout.minimumWidth: 40 + Layout.preferredWidth: 40 + Layout.maximumWidth: 40 + } + + // row 2 + ToggleSwitch { + id: checkBoxUPnP + + Layout.row: 1 + Layout.column: 0 + + labelText: qsTr("Use UPnP") + fontPointSize: 10 + + onSwitchToggled: { + ClientWrapper.settingsAdaptor.setUseUPnP(checked) + } + } + + Item { + Layout.row: 1 + Layout.column: 1 + + Layout.fillHeight: true + + Layout.minimumWidth: 40 + Layout.preferredWidth: 40 + Layout.maximumWidth: 40 + } + + // row 3 + ToggleSwitch { + id: checkBoxTurnEnable + + Layout.row: 2 + Layout.column: 0 + + labelText: qsTr("Use TURN") + fontPointSize: 10 + + onSwitchToggled: { + ClientWrapper.settingsAdaptor.setUseTURN(checked) + } + } + + // row 4 + Label { + Layout.row: 3 + Layout.column: 0 + + Layout.minimumWidth: 124 + + Layout.minimumHeight: 27 + Layout.preferredHeight: 27 + Layout.maximumHeight: 27 + + text: qsTr("TURN Address") + + font.pointSize: 10 + font.kerning: true + + horizontalAlignment: Text.AlignLeft + verticalAlignment: Text.AlignVCenter + } + + InfoLineEdit { + id: lineEditTurnAddress + + Layout.row: 3 + Layout.column: 2 + + fieldLayoutWidth: 300 + fieldLayoutHeight: 29 + + font.pointSize: 10 + font.kerning: true + + horizontalAlignment: Text.AlignLeft + verticalAlignment: Text.AlignVCenter + + onEditingFinished: { + ClientWrapper.settingsAdaptor.setTURNAddress(text) + } + } + + //row 5 + Label { + Layout.row: 4 + Layout.column: 0 + + Layout.minimumWidth: 124 + + Layout.minimumHeight: 27 + Layout.preferredHeight: 27 + Layout.maximumHeight: 27 + + text: qsTr("TURN Username") + + font.pointSize: 10 + font.kerning: true + + horizontalAlignment: Text.AlignLeft + verticalAlignment: Text.AlignVCenter + } + + InfoLineEdit { + id: lineEditTurnUsername + + Layout.row: 4 + Layout.column: 2 + + fieldLayoutWidth: 300 + fieldLayoutHeight: 29 + + font.pointSize: 10 + font.kerning: true + + horizontalAlignment: Text.AlignLeft + verticalAlignment: Text.AlignVCenter + + onEditingFinished: { + ClientWrapper.settingsAdaptor.setTURNUsername(text) + } + } + + //row 6 + Label { + Layout.row: 5 + Layout.column: 0 + + Layout.minimumWidth: 124 + + Layout.minimumHeight: 27 + Layout.preferredHeight: 27 + Layout.maximumHeight: 27 + + text: qsTr("TURN Password") + + font.pointSize: 10 + font.kerning: true + + horizontalAlignment: Text.AlignLeft + verticalAlignment: Text.AlignVCenter + } + + InfoLineEdit { + id: lineEditTurnPassword + layer.mipmap: false + + Layout.row: 5 + Layout.column: 2 + + fieldLayoutWidth: 300 + fieldLayoutHeight: 29 + + font.pointSize: 10 + font.kerning: true + + horizontalAlignment: Text.AlignLeft + verticalAlignment: Text.AlignVCenter + echoMode: TextInput.Password + + onEditingFinished: { + ClientWrapper.settingsAdaptor.setTURNPassword(text) + } + } + + // row 7 + ToggleSwitch { + id: checkBoxSTUNEnable + + Layout.row: 6 + Layout.column: 0 + + labelText: qsTr("Use STUN") + fontPointSize: 10 + + onSwitchToggled: { + ClientWrapper.settingsAdaptor.setUseSTUN(checked) + lineEditSTUNAddress.enabled = checked + } + } + + InfoLineEdit { + id: lineEditSTUNAddress + + Layout.row: 6 + Layout.column: 2 + + fieldLayoutWidth: 300 + fieldLayoutHeight: 29 + + font.pointSize: 10 + font.kerning: true + + placeholderText: qsTr("STUN Address") + + horizontalAlignment: Text.AlignLeft + verticalAlignment: Text.AlignVCenter + + onEditingFinished: { + ClientWrapper.settingsAdaptor.setSTUNAddress(text) + } + } + } + } + } + + Item { + Layout.fillWidth: true + + Layout.minimumHeight: 20 + Layout.preferredHeight: 20 + Layout.maximumHeight: 20 + } + + ColumnLayout { + spacing: 6 + Layout.fillWidth: true + + Label { + Layout.fillWidth: true + Layout.topMargin: 10 + + Layout.minimumHeight: 27 + Layout.preferredHeight: 27 + Layout.maximumHeight: 27 + + text: qsTr("Media") + font.pointSize: 13 + font.kerning: true + + horizontalAlignment: Text.AlignLeft + verticalAlignment: Text.AlignVCenter + } + + Item { + Layout.fillWidth: true + + Layout.minimumHeight: 10 + Layout.preferredHeight: 10 + Layout.maximumHeight: 10 + } + + ColumnLayout { + spacing: 6 + Layout.fillWidth: true + + ToggleSwitch { + id: videoCheckBox + + Layout.leftMargin: 20 + + labelText: qsTr("Enable Video") + fontPointSize: 10 + + onSwitchToggled: { + ClientWrapper.settingsAdaptor.setVideoState(checked) + } + } + + RowLayout { + spacing: 6 + Layout.fillWidth: true + Layout.leftMargin: 20 + + ColumnLayout { + spacing: 6 + //Layout.fillWidth: true + Layout.maximumWidth: 348 + + RowLayout { + spacing: 6 + Layout.fillWidth: true + + Layout.maximumHeight: 30 + + Label { + Layout.fillWidth: true + + Layout.minimumHeight: 30 + Layout.preferredHeight: 30 + Layout.maximumHeight: 30 + + text: qsTr("Video Codecs") + font.pointSize: 10 + font.kerning: true + + horizontalAlignment: Text.AlignLeft + verticalAlignment: Text.AlignVCenter + } + + Item { + Layout.fillHeight: true + + Layout.minimumWidth: 20 + Layout.preferredWidth: 20 + Layout.maximumWidth: 20 + } + + HoverableRadiusButton { + id: videoDownPushButton + + Layout.minimumWidth: 30 + Layout.preferredWidth: 30 + Layout.maximumWidth: 30 + + Layout.minimumHeight: 30 + Layout.preferredHeight: 30 + Layout.maximumHeight: 30 + + buttonImageHeight: height + buttonImageWidth: height + radius: height / 2 + scale: 1 + + font.pointSize: 9 + font.kerning: true + + icon.source: "qrc:/images/icons/round-arrow_drop_down-24px.svg" + icon.width: 32 + icon.height: 32 + + onClicked: { + decreaseVideoCodecPriority() + } + } + + HoverableRadiusButton { + id: videoUpPushButton + + Layout.minimumWidth: 30 + Layout.preferredWidth: 30 + Layout.maximumWidth: 30 + + Layout.minimumHeight: 30 + Layout.preferredHeight: 30 + Layout.maximumHeight: 30 + + buttonImageHeight: height + buttonImageWidth: height + radius: height / 2 + + font.pointSize: 9 + font.kerning: true + + icon.source: "qrc:/images/icons/round-arrow_drop_up-24px.svg" + icon.width: 32 + icon.height: 32 + + onClicked: { + increaseVideoCodecPriority() + } + } + } + + ListViewJami { + id: videoListWidget + + Layout.minimumWidth: 348 + Layout.preferredWidth: 348 + Layout.maximumWidth: 348 + + Layout.minimumHeight: 192 + Layout.preferredHeight: 192 + Layout.maximumHeight: 192 + + model: videoCodecListModel + + delegate: VideoCodecDelegate { + id: videoCodecDelegate + + width: videoListWidget.width + height: videoListWidget.height / 4 + + videoCodecName : VideoCodecName + isEnabled : IsEnabled + videoCodecId: VideoCodecID + + onClicked: { + videoListWidget.currentIndex = index + } + + onVideoCodecStateChange:{ + ClientWrapper.settingsAdaptor.videoCodecsStateChange(idToSet , isToBeEnabled) + updateVideoCodecs() + } + } + } + } + + ColumnLayout { + spacing: 6 + Layout.maximumWidth: 348 + + RowLayout { + spacing: 6 + Layout.fillWidth: true + + Layout.maximumHeight: 30 + + Label { + Layout.fillWidth: true + + Layout.minimumHeight: 30 + Layout.preferredHeight: 30 + Layout.maximumHeight: 30 + + text: qsTr("Audio Codecs") + font.pointSize: 10 + font.kerning: true + + horizontalAlignment: Text.AlignLeft + verticalAlignment: Text.AlignVCenter + } + + Item { + Layout.fillHeight: true + + Layout.minimumWidth: 20 + Layout.preferredWidth: 20 + Layout.maximumWidth: 20 + } + + HoverableRadiusButton { + id: audioDownPushButton + + Layout.minimumWidth: 30 + Layout.preferredWidth: 30 + Layout.maximumWidth: 30 + + Layout.minimumHeight: 30 + Layout.preferredHeight: 30 + Layout.maximumHeight: 30 + + radius: height / 2 + buttonImageHeight: height + buttonImageWidth: height + + font.pointSize: 9 + font.kerning: true + + icon.source: "qrc:/images/icons/round-arrow_drop_down-24px.svg" + icon.width: 32 + icon.height: 32 + + onClicked: { + decreaseAudioCodecPriority() + } + } + + HoverableRadiusButton { + id: audioUpPushButton + + Layout.minimumWidth: 30 + Layout.preferredWidth: 30 + Layout.maximumWidth: 30 + + Layout.minimumHeight: 30 + Layout.preferredHeight: 30 + Layout.maximumHeight: 30 + + buttonImageHeight: height + buttonImageWidth: height + + radius: height / 2 + + font.pointSize: 9 + font.kerning: true + + icon.source: "qrc:/images/icons/round-arrow_drop_up-24px.svg" + icon.width: 32 + icon.height: 32 + + onClicked: { + increaseAudioCodecPriority() + } + } + } + + ListViewJami { + id: audioListWidget + + Layout.minimumWidth: 348 + Layout.preferredWidth: 348 + Layout.maximumWidth: 348 + + Layout.minimumHeight: 192 + Layout.preferredHeight: 192 + Layout.maximumHeight: 192 + + model: audioCodecListModel + + delegate: AudioCodecDelegate { + id: audioCodecDelegate + + width: audioListWidget.width + height: audioListWidget.height / 4 + + layer.mipmap: false + clip: true + + audioCodecName : AudioCodecName + isEnabled : IsEnabled + audioCodecId: AudioCodecID + samplerRate: Samplerate + + onClicked: { + audioListWidget.currentIndex = index + } + + onAudioCodecStateChange:{ + ClientWrapper.settingsAdaptor.audioCodecsStateChange(idToSet , isToBeEnabled) + updateAudioCodecs() + } + } + } + } + } + } + } + + Item { + Layout.fillWidth: true + + Layout.minimumHeight: 48 + Layout.preferredHeight: 48 + Layout.maximumHeight: 48 + } +} diff --git a/src/settingsview/components/AudioCodecDelegate.qml b/src/settingsview/components/AudioCodecDelegate.qml new file mode 100644 index 00000000..9f80a2e1 --- /dev/null +++ b/src/settingsview/components/AudioCodecDelegate.qml @@ -0,0 +1,102 @@ +/* + * Copyright (C) 2019-2020 by Savoir-faire Linux + * Author: Yang Wang + * + * 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 . + */ + +import QtQuick 2.15 +import QtQuick.Window 2.15 +import QtQuick.Controls 2.15 +import QtQuick.Controls.Universal 2.12 +import QtQuick.Layouts 1.3 +import QtGraphicalEffects 1.14 +import QtQuick.Controls.Styles 1.4 +import net.jami.Models 1.0 + +ItemDelegate { + id: videoCodecDelegate + + property string audioCodecName : "" + property bool isEnabled : false + property int audioCodecId + property string samplerRate: "" + + signal audioCodecStateChange(string idToSet , bool isToBeEnabled) + + property int checkBoxWidth: 10 + + highlighted: ListView.isCurrentItem + + RowLayout{ + anchors.fill: parent + z: 1 + + spacing: 10 + + CheckBox{ + id: checkBoxIsEnabled + + Layout.leftMargin: 20 + + Layout.alignment: Qt.AlignLeft | Qt.AlignVCenter + Layout.fillHeight: true + + Layout.minimumWidth: checkBoxWidth + Layout.preferredWidth: checkBoxWidth + Layout.maximumWidth: checkBoxWidth + + tristate: false + checkState: isEnabled ? Qt.Checked : Qt.Unchecked + + indicator.implicitWidth: checkBoxWidth + indicator.implicitHeight:checkBoxWidth + + indicator.layer.textureSize.width: checkBoxWidth + indicator.layer.textureSize.height: checkBoxWidth + + text: "" + + nextCheckState: function() { + var result + var result_bool + + if (checkState === Qt.Checked){ + result = Qt.Unchecked + result_bool = false + } else { + result = Qt.Checked + result_bool = true + } + audioCodecStateChange(audioCodecId,result_bool) + return result + } + } + + Label{ + id: formatNameLabel + + Layout.alignment: Qt.AlignLeft | Qt.AlignVCenter + horizontalAlignment: Text.AlignLeft + verticalAlignment: Text.AlignVCenter + + Layout.fillWidth: true + Layout.fillHeight: true + + text: audioCodecName + " " + samplerRate + " Hz" + font.pointSize: 8 + font.kerning: true + } + } +} diff --git a/src/settingsview/components/AvSettingPage.qml b/src/settingsview/components/AvSettingPage.qml new file mode 100644 index 00000000..a999e32f --- /dev/null +++ b/src/settingsview/components/AvSettingPage.qml @@ -0,0 +1,832 @@ +/* + * Copyright (C) 2019-2020 by Savoir-faire Linux + * Author: Yang Wang + * + * 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 . + */ + +import QtQuick 2.15 +import QtQuick.Window 2.14 +import QtQuick.Controls 2.15 +import QtQuick.Controls.Universal 2.12 +import QtQuick.Layouts 1.3 +import QtGraphicalEffects 1.14 +import QtQuick.Controls.Styles 1.4 +import net.jami.Models 1.0 + +Rectangle { + id: avSettingPage + + AudioInputDeviceModel{ + id: audioInputDeviceModel + } + + AudioOutputDeviceModel{ + id: audioOutputDeviceModel + } + + AudioManagerListModel{ + id: audioManagerListModel + } + + VideoInputDeviceModel{ + id: videoInputDeviceModel + } + + VideoFormatResolutionModel{ + id: videoFormatResolutionModel + } + + VideoFormatFpsModel{ + id: videoFormatFpsModel + } + + function populateAVSettings(){ + audioInputDeviceModel.reset() + audioOutputDeviceModel.reset() + + inputComboBox.currentIndex = audioInputDeviceModel.getCurrentSettingIndex() + outputComboBox.currentIndex = audioOutputDeviceModel.getCurrentSettingIndex() + ringtoneDeviceComboBox.currentIndex = audioOutputDeviceModel.getCurrentRingtoneDeviceIndex() + + audioManagerRowLayout.visible = (audioManagerListModel.rowCount() > 0) + if(audioManagerListModel.rowCount() > 0){ + audioManagerComboBox.currentIndex = audioManagerListModel.getCurrentSettingIndex() + } + + populateVideoSettings() + var encodeAccel = ClientWrapper.avmodel.getHardwareAcceleration() + hardwareAccelControl.checked = encodeAccel + } + + function populateVideoSettings() { + videoInputDeviceModel.reset() + + deviceBox.enabled = (videoInputDeviceModel.deviceCount() > 0) + resolutionBox.enabled = (videoInputDeviceModel.deviceCount() > 0) + fpsBox.enabled = (videoInputDeviceModel.deviceCount() > 0) + labelVideoDevice.enabled = (videoInputDeviceModel.deviceCount() > 0) + labelVideoResolution.enabled = (videoInputDeviceModel.deviceCount() > 0) + labelVideoFps.enabled = (videoInputDeviceModel.deviceCount() > 0) + + deviceBox.currentIndex = videoInputDeviceModel.getCurrentSettingIndex() + slotDeviceBoxCurrentIndexChanged(deviceBox.currentIndex) + + try{ + startPreviewing(false) + } catch (err2){ console.log("Start preview fail when populate video settings, exception: "+ err2.message)} + + } + + function setFormatListForCurrentDevice(){ + var device = ClientWrapper.avmodel.getCurrentVideoCaptureDevice() + if(ClientWrapper.settingsAdaptor.get_DeviceCapabilitiesSize(device) === 0){ + return + } + + try{ + videoFormatResolutionModel.reset() + resolutionBox.currentIndex = videoFormatResolutionModel.getCurrentSettingIndex() + slotFormatCurrentIndexChanged(resolutionBox.currentIndex,true) + } catch(err){console.warn("Exception: " + err.message)} + } + + function startPreviewing(force = false){ + ClientWrapper.accountAdaptor.startPreviewing(force) + previewAvailable = true + } + + function stopPreviewing(){ + ClientWrapper.accountAdaptor.stopPreviewing() + } + + function startAudioMeter(async = true){ + audioInputMeter.start() + ClientWrapper.accountAdaptor.startAudioMeter(async) + } + + function stopAudioMeter(async = true){ + audioInputMeter.stop() + ClientWrapper.accountAdaptor.stopAudioMeter(async) + } + + // slots for av page + function slotAudioMeter(id, level){ + if (id === "audiolayer_id") { + audioInputMeter.setLevel(level) + } + } + + function slotSetHardwareAccel(state){ + ClientWrapper.accountAdaptor.avModel().setHardwareAcceleration(state) + startPreviewing(true) + } + + function slotAudioManagerIndexChanged(index){ + stopAudioMeter(false) + var selectedAudioManager = audioManagerListModel.data(audioManagerListModel.index( + index, 0), AudioManagerListModel.AudioManagerID) + ClientWrapper.avmodel.setAudioManager(selectedAudioManager) + startAudioMeter(false) + } + + function slotRingtoneDeviceIndexChanged(index){ + stopAudioMeter(false) + var selectedRingtoneDeviceName = audioOutputDeviceModel.data(audioOutputDeviceModel.index( + index, 0), AudioOutputDeviceModel.Device_ID) + ClientWrapper.avmodel.setRingtoneDevice(selectedRingtoneDeviceName) + startAudioMeter(false) + } + + function slotAudioOutputIndexChanged(index){ + stopAudioMeter(false) + var selectedOutputDeviceName = audioOutputDeviceModel.data(audioOutputDeviceModel.index( + index, 0), AudioOutputDeviceModel.Device_ID) + ClientWrapper.avmodel.setOutputDevice(selectedOutputDeviceName) + startAudioMeter(false) + } + + function slotAudioInputIndexChanged(index){ + stopAudioMeter(false) + var selectedInputDeviceName = audioInputDeviceModel.data(audioInputDeviceModel.index( + index, 0), AudioInputDeviceModel.Device_ID) + + ClientWrapper.avmodel.setInputDevice(selectedInputDeviceName) + startAudioMeter(false) + } + + function slotDeviceBoxCurrentIndexChanged(index){ + if(videoInputDeviceModel.deviceCount() <= 0){ + return + } + + try{ + var deviceId = videoInputDeviceModel.data(videoInputDeviceModel.index( + index, 0), VideoInputDeviceModel.DeviceId) + var deviceName = videoInputDeviceModel.data(videoInputDeviceModel.index( + index, 0), VideoInputDeviceModel.DeviceName) + if(deviceId.length === 0){ + console.warn("Couldn't find device: " + deviceName) + return + } + + ClientWrapper.avmodel.setCurrentVideoCaptureDevice(deviceId) + ClientWrapper.avmodel.setDefaultDevice(deviceId) + setFormatListForCurrentDevice() + startPreviewing(true) + } catch(err){console.warn(err.message)} + } + + function slotFormatCurrentIndexChanged(index, isResolutionIndex){ + var resolution + var rate + if(isResolutionIndex){ + resolution = videoFormatResolutionModel.data(videoFormatResolutionModel.index( + index, 0), VideoFormatResolutionModel.Resolution) + videoFormatFpsModel.currentResolution = resolution + fpsBox.currentIndex = videoFormatFpsModel.getCurrentSettingIndex() + rate = videoFormatFpsModel.data(videoFormatFpsModel.index( + fpsBox.currentIndex, 0), VideoFormatFpsModel.FPS) + } else { + resolution = videoFormatResolutionModel.data(videoFormatResolutionModel.index( + resolutionBox.currentIndex, 0), VideoFormatResolutionModel.Resolution) + videoFormatFpsModel.currentResolution = resolution + rate = videoFormatFpsModel.data(videoFormatFpsModel.index( + index, 0), VideoFormatFpsModel.FPS) + } + + try{ + ClientWrapper.settingsAdaptor.set_Video_Settings_Rate_And_Resolution(ClientWrapper.avmodel.getCurrentVideoCaptureDevice(),rate,resolution) + } catch(error){console.warn(error.message)} + } + + function slotVideoDeviceListChanged(){ + populateVideoSettings() + } + + property bool previewAvailable: false + + Connections{ + target: ClientWrapper.avmodel + + function onAudioMeter(id, level){ + slotAudioMeter(id,level) + } + } + + Connections{ + target: ClientWrapper.renderManager + + function onVideoDeviceListChanged(){ + slotVideoDeviceListChanged() + } + } + + Layout.fillHeight: true + Layout.fillWidth: true + + ScrollView{ + anchors.fill: parent + clip: true + + RowLayout { + width: avSettingPage.width + height: avSettingPage.height + + spacing: 0 + Item { + Layout.fillHeight: true + Layout.maximumWidth: 48 + Layout.preferredWidth: 48 + Layout.minimumWidth: 48 + } + + ColumnLayout { + spacing: 7 + + Layout.fillHeight: true + Layout.maximumWidth: 580 + Layout.preferredWidth: 580 + Layout.minimumWidth: 580 + + Item { + Layout.fillWidth: true + Layout.minimumHeight: 10 + Layout.preferredHeight: 10 + Layout.maximumHeight: 10 + } + + Label { + Layout.fillWidth: true + Layout.minimumHeight: 25 + Layout.preferredHeight: 25 + Layout.maximumHeight: 25 + + text: qsTr("Audio / Video") + font.pointSize: 15 + font.kerning: true + + horizontalAlignment: Text.AlignLeft + verticalAlignment: Text.AlignVCenter + } + + Item { + Layout.fillWidth: true + Layout.minimumHeight: 24 + Layout.preferredHeight: 24 + Layout.maximumHeight: 24 + } + + ColumnLayout { + spacing: 0 + Layout.fillWidth: true + + Label { + Layout.fillWidth: true + Layout.minimumHeight: 21 + Layout.preferredHeight: 21 + Layout.maximumHeight: 21 + + text: qsTr("Audio") + font.pointSize: 13 + font.kerning: true + + horizontalAlignment: Text.AlignLeft + verticalAlignment: Text.AlignVCenter + } + + Item { + Layout.fillWidth: true + Layout.minimumHeight: 10 + Layout.preferredHeight: 10 + Layout.maximumHeight: 10 + } + + ColumnLayout { + spacing: 7 + Layout.fillWidth: true + + RowLayout { + spacing: 7 + Layout.leftMargin: 20 + Layout.fillWidth: true + Layout.maximumHeight: 30 + + Label { + Layout.maximumWidth: 77 + Layout.preferredWidth: 77 + Layout.minimumWidth: 77 + + Layout.minimumHeight: 30 + Layout.preferredHeight: 30 + Layout.maximumHeight: 30 + + text: qsTr("Microphone") + font.pointSize: 11 + font.kerning: true + + horizontalAlignment: Text.AlignLeft + verticalAlignment: Text.AlignVCenter + } + + Item { + Layout.fillWidth: true + Layout.fillHeight: true + } + + SettingParaCombobox { + id: inputComboBox + + Layout.maximumWidth: 360 + Layout.preferredWidth: 360 + Layout.minimumWidth: 360 + + Layout.minimumHeight: 30 + Layout.preferredHeight: 30 + Layout.maximumHeight: 30 + + font.pointSize: 10 + font.kerning: true + + model: audioInputDeviceModel + + textRole: "ID_UTF8" + + onActivated: { + slotAudioInputIndexChanged(index) + } + } + } + + // the audio level meter + LevelMeter { + id: audioInputMeter + + Layout.leftMargin: 20 + + Layout.fillWidth: true + + Layout.minimumHeight: 10 + Layout.preferredHeight: 10 + Layout.maximumHeight: 10 + + indeterminate: false + from: 0 + to: 100 + } + + Item { + Layout.fillWidth: true + + Layout.minimumHeight: 5 + Layout.preferredHeight: 5 + Layout.maximumHeight: 5 + } + + RowLayout { + spacing: 7 + Layout.leftMargin: 20 + Layout.fillWidth: true + Layout.maximumHeight: 30 + + Label { + Layout.maximumWidth: 95 + Layout.preferredWidth: 95 + Layout.minimumWidth: 95 + + Layout.minimumHeight: 30 + Layout.preferredHeight: 30 + Layout.maximumHeight: 30 + + text: qsTr("Output Device") + font.pointSize: 11 + font.kerning: true + + horizontalAlignment: Text.AlignLeft + verticalAlignment: Text.AlignVCenter + } + + Item { + Layout.fillWidth: true + Layout.fillHeight: true + } + + SettingParaCombobox { + id: outputComboBox + + Layout.maximumWidth: 360 + Layout.preferredWidth: 360 + Layout.minimumWidth: 360 + + Layout.minimumHeight: 30 + Layout.preferredHeight: 30 + Layout.maximumHeight: 30 + + font.pointSize: 10 + font.kerning: true + + model: audioOutputDeviceModel + + textRole: "ID_UTF8" + + onActivated: { + slotAudioOutputIndexChanged(index) + } + } + } + + RowLayout { + spacing: 7 + Layout.leftMargin: 20 + Layout.fillWidth: true + Layout.maximumHeight: 30 + + Label { + Layout.maximumWidth: 77 + Layout.preferredWidth: 77 + Layout.minimumWidth: 77 + + Layout.minimumHeight: 30 + Layout.preferredHeight: 30 + Layout.maximumHeight: 30 + + text: qsTr("Ringtone Device") + font.pointSize: 11 + font.kerning: true + + horizontalAlignment: Text.AlignLeft + verticalAlignment: Text.AlignVCenter + } + + Item { + Layout.fillWidth: true + Layout.fillHeight: true + } + + SettingParaCombobox { + id: ringtoneDeviceComboBox + + Layout.maximumWidth: 360 + Layout.preferredWidth: 360 + Layout.minimumWidth: 360 + + Layout.minimumHeight: 30 + Layout.preferredHeight: 30 + Layout.maximumHeight: 30 + + font.pointSize: 10 + font.kerning: true + + model: audioOutputDeviceModel + + textRole: "ID_UTF8" + + onActivated: { + slotRingtoneDeviceIndexChanged(index) + } + } + } + + RowLayout { + id: audioManagerRowLayout + + spacing: 7 + Layout.leftMargin: 20 + Layout.fillWidth: true + Layout.maximumHeight: 30 + + Label { + Layout.maximumWidth: 77 + Layout.preferredWidth: 77 + Layout.minimumWidth: 77 + + Layout.minimumHeight: 30 + Layout.preferredHeight: 30 + Layout.maximumHeight: 30 + + text: qsTr("Audio Manager") + font.pointSize: 11 + font.kerning: true + + horizontalAlignment: Text.AlignLeft + verticalAlignment: Text.AlignVCenter + } + + Item { + Layout.fillWidth: true + Layout.fillHeight: true + } + + SettingParaCombobox { + id: audioManagerComboBox + + Layout.maximumWidth: 360 + Layout.preferredWidth: 360 + Layout.minimumWidth: 360 + + Layout.minimumHeight: 30 + Layout.preferredHeight: 30 + Layout.maximumHeight: 30 + + font.pointSize: 10 + font.kerning: true + + model: audioManagerListModel + + textRole: "ID_UTF8" + + onActivated: { + slotAudioManagerIndexChanged(index) + } + } + } + } + } + + Item { + Layout.fillWidth: true + + Layout.minimumHeight: 20 + Layout.preferredHeight: 20 + Layout.maximumHeight: 20 + } + + ColumnLayout { + spacing: 7 + Layout.fillWidth: true + + Label { + Layout.fillWidth: true + Layout.minimumHeight: 30 + Layout.preferredHeight: 30 + Layout.maximumHeight: 30 + + text: qsTr("Video") + font.pointSize: 13 + font.kerning: true + + horizontalAlignment: Text.AlignLeft + verticalAlignment: Text.AlignVCenter + } + + Item { + Layout.fillWidth: true + + Layout.minimumHeight: 10 + Layout.preferredHeight: 10 + Layout.maximumHeight: 10 + } + + ColumnLayout { + spacing: 6 + RowLayout { + spacing: 7 + Layout.fillWidth: true + Layout.leftMargin: 20 + Layout.maximumHeight: 30 + + Label { + id: labelVideoDevice + + Layout.maximumWidth: 44 + Layout.preferredWidth: 44 + Layout.minimumWidth: 44 + + Layout.minimumHeight: 30 + Layout.preferredHeight: 30 + Layout.maximumHeight: 30 + + text: qsTr("Device") + font.pointSize: 11 + font.kerning: true + + horizontalAlignment: Text.AlignLeft + verticalAlignment: Text.AlignVCenter + } + + Item { + Layout.fillHeight: true + Layout.fillWidth: true + } + + SettingParaCombobox { + id: deviceBox + + Layout.maximumWidth: 360 + Layout.preferredWidth: 360 + Layout.minimumWidth: 360 + + Layout.minimumHeight: 30 + Layout.preferredHeight: 30 + Layout.maximumHeight: 30 + + font.pointSize: 10 + font.kerning: true + + model: videoInputDeviceModel + + textRole: "DeviceName_UTF8" + + onActivated: { + slotDeviceBoxCurrentIndexChanged(index) + } + } + } + + RowLayout { + spacing: 7 + Layout.fillWidth: true + Layout.leftMargin: 20 + Layout.maximumHeight: 30 + + Label { + id: labelVideoResolution + + Layout.maximumWidth: 47 + Layout.preferredWidth: 47 + Layout.minimumWidth: 47 + + Layout.minimumHeight: 30 + Layout.preferredHeight: 30 + Layout.maximumHeight: 30 + + text: qsTr("Resolution") + font.pointSize: 11 + font.kerning: true + + horizontalAlignment: Text.AlignLeft + verticalAlignment: Text.AlignVCenter + } + + Item { + Layout.fillHeight: true + Layout.fillWidth: true + } + + SettingParaCombobox { + id: resolutionBox + + Layout.maximumWidth: 360 + Layout.preferredWidth: 360 + Layout.minimumWidth: 360 + + Layout.minimumHeight: 30 + Layout.preferredHeight: 30 + Layout.maximumHeight: 30 + + font.pointSize: 10 + font.kerning: true + + model: videoFormatResolutionModel + textRole: "Resolution_UTF8" + + onActivated: { + slotFormatCurrentIndexChanged(index,true) + } + } + } + + RowLayout { + spacing: 7 + Layout.fillWidth: true + Layout.leftMargin: 20 + Layout.maximumHeight: 30 + + Label { + id: labelVideoFps + + Layout.maximumWidth: 47 + Layout.preferredWidth: 47 + Layout.minimumWidth: 47 + + Layout.minimumHeight: 30 + Layout.preferredHeight: 30 + Layout.maximumHeight: 30 + + text: qsTr("Fps") + font.pointSize: 11 + font.kerning: true + + horizontalAlignment: Text.AlignLeft + verticalAlignment: Text.AlignVCenter + } + + Item { + Layout.fillHeight: true + Layout.fillWidth: true + } + + SettingParaCombobox { + id: fpsBox + + Layout.maximumWidth: 360 + Layout.preferredWidth: 360 + Layout.minimumWidth: 360 + + Layout.minimumHeight: 30 + Layout.preferredHeight: 30 + Layout.maximumHeight: 30 + + font.pointSize: 10 + font.kerning: true + + model: videoFormatFpsModel + textRole: "FPS_ToDisplay_UTF8" + + onActivated: { + slotFormatCurrentIndexChanged(index,false) + } + } + } + } + } + + Item { + Layout.fillWidth: true + Layout.minimumHeight: 20 + Layout.preferredHeight: 20 + Layout.maximumHeight: 20 + } + + RowLayout{ + Layout.alignment: Qt.AlignHCenter + + Layout.preferredWidth: 580 + Layout.minimumWidth: 580 + + Layout.minimumHeight: 224 + Layout.preferredHeight: 224 + Layout.maximumHeight: 224 + + Rectangle { + Layout.alignment: Qt.AlignHCenter + Layout.fillHeight: true + Layout.minimumWidth: 580 + + color: "black" + + PreviewRenderer{ + id: peviewWidget + + visible: previewAvailable + height: parent.height + width: 224 + x: (parent.width - width) /2 + y: 0 + } + } + } + + Label { + visible: !previewAvailable + + Layout.fillWidth: true + + Layout.minimumHeight: 30 + Layout.preferredHeight: 30 + Layout.maximumHeight: 30 + + text: qsTr("Preview unavailable") + font.pointSize: 10 + font.kerning: true + + horizontalAlignment: Text.AlignHCenter + verticalAlignment: Text.AlignVCenter + } + + // Toggle switch to enable hardware acceleration + ToggleSwitch { + id: hardwareAccelControl + + labelText: "Enable hardware acceleration" + + onSwitchToggled: { + slotSetHardwareAccel(checked) + } + } + + Item { + Layout.fillHeight: true + Layout.fillWidth: true + } + } + + Item { + Layout.fillHeight: true + Layout.fillWidth: true + } + } + + } +} diff --git a/src/settingsview/components/BannedItemDelegate.qml b/src/settingsview/components/BannedItemDelegate.qml new file mode 100644 index 00000000..980d539a --- /dev/null +++ b/src/settingsview/components/BannedItemDelegate.qml @@ -0,0 +1,206 @@ +/* + * Copyright (C) 2019-2020 by Savoir-faire Linux + * Author: Yang Wang + * + * 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 . + */ + +import QtQuick 2.15 +import QtQuick.Window 2.15 +import QtQuick.Controls 2.15 +import QtQuick.Controls.Universal 2.12 +import QtQuick.Layouts 1.3 +import QtGraphicalEffects 1.14 +import QtQuick.Controls.Styles 1.4 +import net.jami.Models 1.0 + +import "../../commoncomponents" + +ItemDelegate { + id: deviceItemDelegate + + property string contactName : "" + property string contactID: "" + property string contactPicture_base64:"" + + signal btnReAddContactClicked + + function btnReAddContactEnter(){ + btnReAddContact.enterBtn() + } + + function btnReAddContactExit(){ + btnReAddContact.exitBtn() + } + + function btnReAddContactPress(){ + btnReAddContact.pressBtn() + } + + function btnReAddContactRelease(){ + btnReAddContact.releaseBtn() + } + + highlighted: ListView.isCurrentItem + + RowLayout{ + anchors.fill: parent + + spacing: 7 + + Label{ + id: labelContactAvatar + + Layout.alignment: Qt.AlignVCenter + + Layout.leftMargin: 7 + Layout.topMargin: 7 + Layout.bottomMargin: 7 + + Layout.minimumWidth: 48 + Layout.preferredWidth: 48 + Layout.maximumWidth: 48 + + Layout.minimumHeight: 48 + Layout.preferredHeight: 48 + Layout.maximumHeight: 48 + + background: Rectangle{ + anchors.fill: parent + color: "transparent" + Image { + id: avatarImg + + anchors.fill: parent + source: "data:image/png;base64," + contactPicture_base64 + fillMode: Image.PreserveAspectCrop + layer.enabled: true + layer.effect: OpacityMask { + maskSource: Rectangle{ + width: avatarImg.width + height: avatarImg.height + radius: { + var size = ((avatarImg.width <= avatarImg.height)? avatarImg.width:avatarImg.height) + return size /2 + } + } + } + } + } + } + + Item{ + Layout.minimumWidth: 8 + Layout.preferredWidth: 8 + Layout.maximumWidth: 8 + + Layout.minimumHeight: 20 + Layout.preferredHeight: 20 + Layout.maximumHeight: 20 + } + + ColumnLayout{ + Layout.fillWidth: true + Layout.fillHeight: true + + Layout.topMargin: 7 + Layout.bottomMargin: 7 + + Layout.alignment: Qt.AlignVCenter + + spacing: 7 + + Label{ + id: labelContactName + + Layout.fillWidth: true + Layout.minimumWidth: 0 + Layout.maximumWidth: 16777215 + + Layout.minimumHeight: 30 + Layout.preferredHeight: 30 + Layout.maximumHeight: 30 + + font.pointSize: 8 + font.kerning: true + + horizontalAlignment: Text.AlignLeft + verticalAlignment: Text.AlignVCenter + + text: contactName === "" ? qsTr("name") : contactName + } + + Label{ + id: labelContactId + + Layout.fillWidth: true + Layout.minimumWidth: 0 + Layout.maximumWidth: 16777215 + + Layout.minimumHeight: 30 + Layout.preferredHeight: 30 + Layout.maximumHeight: 30 + + font.pointSize: 8 + font.kerning: true + + horizontalAlignment: Qt.AlignLeft + verticalAlignment: Qt.AlignVCenter + + text: contactID === "" ? qsTr("id") : contactID + } + } + + HoverableRadiusButton{ + id: btnReAddContact + + Layout.topMargin: 7 + Layout.bottomMargin: 7 + + Layout.minimumWidth: 30 + Layout.preferredWidth: 30 + Layout.maximumWidth: 30 + + Layout.minimumHeight: 30 + Layout.preferredHeight: 30 + Layout.maximumHeight: 30 + + font.pointSize: 8 + font.kerning: true + + buttonImageHeight: height + buttonImageWidth: height + + source:"qrc:/images/icons/ic_person_add_black_24dp_2x.png" + + ToolTip.visible: isHovering + ToolTip.text: qsTr("Add as contact") + + onClicked: { + btnReAddContactClicked() + } + } + + Item{ + Layout.rightMargin: 7 + + Layout.minimumWidth: 8 + Layout.preferredWidth: 8 + Layout.maximumWidth: 8 + + Layout.minimumHeight: 20 + } + } +} + diff --git a/src/settingsview/components/CurrentAccountSettingsScrollPage.qml b/src/settingsview/components/CurrentAccountSettingsScrollPage.qml new file mode 100644 index 00000000..b3d43923 --- /dev/null +++ b/src/settingsview/components/CurrentAccountSettingsScrollPage.qml @@ -0,0 +1,1376 @@ +/* + * Copyright (C) 2019-2020 by Savoir-faire Linux + * Author: Yang Wang + * + * 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 . + */ + +import QtQuick 2.15 +import QtQuick.Window 2.14 +import QtQuick.Controls 2.14 +import QtQuick.Controls.Universal 2.12 +import QtQuick.Layouts 1.3 +import QtGraphicalEffects 1.14 +import QtQuick.Controls.Styles 1.4 +import QtQuick.Dialogs 1.3 +import Qt.labs.platform 1.1 +import net.jami.Models 1.0 + +import "../../commoncomponents" + +Rectangle { + id: accountViewRect + + enum RegName { + BLANK, + INVALIDFORM, + TAKEN, + FREE, + SEARCHING + } + + property int regNameUi: CurrentAccountSettingsScrollPage.BLANK + property string registeredName: "" + property bool registeredIdNeedsSet: false + + property int refreshVariable : 0 + + signal navigateToMainView + signal navigateToNewWizardView + + function refreshRelevantUI(){ + refreshVariable++ + refreshVariable-- + } + + Connections { + id: btnRegisterNameClickConnection + target: btnRegisterName + + enabled: { + refreshVariable + switch (regNameUi) { + case CurrentAccountSettingsScrollPage.FREE: + return true + default: + return false + } + } + + function onClicked() { + slotRegisterName() + } + } + + function updateAccountInfoDisplayed() { + setAvatar() + + accountEnableCheckBox.checked = ClientWrapper.settingsAdaptor.get_CurrentAccountInfo_Enabled() + displayNameLineEdit.text = ClientWrapper.settingsAdaptor.getCurrentAccount_Profile_Info_Alias() + + var showLocalAccountConfig = (ClientWrapper.settingsAdaptor.getAccountConfig_Manageruri() === "") + passwdPushButton.visible = showLocalAccountConfig + btnExportAccount.visible = showLocalAccountConfig + linkDevPushButton.visible = showLocalAccountConfig + + registeredIdNeedsSet = (ClientWrapper.settingsAdaptor.get_CurrentAccountInfo_RegisteredName() === "") + + if(!registeredIdNeedsSet){ + currentRegisteredID.text = ClientWrapper.settingsAdaptor.get_CurrentAccountInfo_RegisteredName() + } else { + currentRegisteredID.text = "" + } + + currentRingID.text = ClientWrapper.settingsAdaptor.getCurrentAccount_Profile_Info_Uri() + + // update device list view + updateAndShowDevicesSlot() + + bannedContactsListWidget.visible = false + bannedContactsLayoutWidget.visible = (bannedListModel.rowCount() > 0) + + if (advanceSettingsView.visible) { + advanceSettingsView.updateAccountInfoDisplayedAdvance() + } + refreshRelevantUI() + } + + function connectCurrentAccount() { + accountConnections_ContactModel.enabled = true + accountConnections_DeviceModel.enabled = true + } + + function disconnectAccountConnections() { + accountConnections_ContactModel.enabled = false + accountConnections_DeviceModel.enabled = false + } + + function isPhotoBoothOpened() { + return currentAccountAvatar.takePhotoState + } + + function setAvatar() { + currentAccountAvatar.setAvatarPixmap( + ClientWrapper.settingsAdaptor.getAvatarImage_Base64( + currentAccountAvatar.boothWidht), + ClientWrapper.settingsAdaptor.getIsDefaultAvatar()) + } + + function stopBooth() { + currentAccountAvatar.stopBooth() + } + + function toggleBannedContacts(){ + var bannedContactsVisible = bannedContactsListWidget.visible + bannedContactsListWidget.visible = !bannedContactsVisible + updateAndShowBannedContactsSlot() + } + + function unban(index){ + ClientWrapper.settingsAdaptor.unbanContact(index) + updateAndShowBannedContactsSlot() + } + + Connections { + id: accountConnections_ContactModel + target: ClientWrapper.contactModel + + function onModelUpdated(uri, needsSorted) { + updateAndShowBannedContactsSlot() + } + + function onContactAdded(contactUri){ + updateAndShowBannedContactsSlot() + } + + function onContactRemoved(contactUri){ + updateAndShowBannedContactsSlot() + } + } + + Connections { + id: accountConnections_DeviceModel + target: ClientWrapper.deviceModel + + function onDeviceAdded(id) { + updateAndShowDevicesSlot() + } + + function onDeviceRevoked(id, status) { + updateAndShowDevicesSlot() + } + + function onDeviceUpdated(id) { + updateAndShowDevicesSlot() + } + } + + // slots + function verifyRegisteredNameSlot() { + if (ClientWrapper.settingsAdaptor.get_CurrentAccountInfo_RegisteredName() !== "") { + regNameUi = CurrentAccountSettingsScrollPage.BLANK + } else { + registeredName = ClientWrapper.utilsAdaptor.stringSimplifier( + currentRegisteredID.text) + if (registeredName !== "") { + if (ClientWrapper.utilsAdaptor.validateRegNameForm(registeredName)) { + regNameUi = CurrentAccountSettingsScrollPage.SEARCHING + lookUpLabelTimer.restart() + } else { + regNameUi = CurrentAccountSettingsScrollPage.INVALIDFORM + } + } else { + regNameUi = CurrentAccountSettingsScrollPage.BLANK + } + } + } + + Timer { + id: lookUpLabelTimer + + interval: 300 + onTriggered: { + beforeNameLookup() + } + } + + function beforeNameLookup() { + ClientWrapper.nameDirectory.lookupName("", registeredName) + } + + Connections { + target: ClientWrapper.nameDirectory + enabled: true + + function onRegisteredNameFound(status, address, name) { + afterNameLookup(status, name) + } + } + + function afterNameLookup(status, regName) { + if (registeredName === regName && regName.length > 2) { + switch (status) { + case NameDirectory.LookupStatus.NOT_FOUND: + regNameUi = CurrentAccountSettingsScrollPage.FREE + break + default: + regNameUi = CurrentAccountSettingsScrollPage.TAKEN + break + } + } else { + regNameUi = CurrentAccountSettingsScrollPage.BLANK + } + } + + function setAccEnableSlot(state) { + ClientWrapper.accountModel.setAccountEnabled(ClientWrapper.utilsAdaptor.getCurrAccId(), state) + } + + /* + * JamiFileDialog for exporting account + */ + JamiFileDialog { + id: exportBtn_Dialog + + mode: JamiFileDialog.SaveFile + + title: qsTr("Export Account Here") + folder: StandardPaths.writableLocation(StandardPaths.DesktopLocation) + + nameFilters: [qsTr("Jami archive files") + " (*.gz)", qsTr( + "All files") + " (*)"] + + onAccepted: { + // is there password? If so, go to password dialog, else, go to following directly + var exportPath = ClientWrapper.utilsAdaptor.getAbsPath(file.toString()) + if (ClientWrapper.accountAdaptor.hasPassword()) { + passwordDialog.openDialog(PasswordDialog.ExportAccount,exportPath) + return + } else { + if (exportPath.length > 0) { + var isSuccessful = ClientWrapper.accountAdaptor.accoundModel().exportToFile(ClientWrapper.utilsAdaptor.getCurrAccId(), exportPath,"") + var title = isSuccessful ? qsTr("Success") : qsTr("Error") + var iconMode = isSuccessful ? StandardIcon.Information : StandardIcon.Critical + var info = isSuccessful ? qsTr("Export Successful") : qsTr("Export Failed") + msgDialog.openWithParameters(title,info, iconMode, StandardButton.Ok) + } + } + } + + onRejected: {} + + onVisibleChanged: { + if (!visible) { + rejected() + } + } + } + + function exportAccountSlot() { + exportBtn_Dialog.open() + } + + PasswordDialog { + id: passwordDialog + + onDoneSignal: { + var success = (code === successCode) + var title = success ? qsTr("Success") : qsTr("Error") + var iconMode = success ? StandardIcon.Information : StandardIcon.Critical + + var info + switch(currentPurpose){ + case PasswordDialog.ExportAccount: + info = success ? qsTr("Export Successful") : qsTr("Export Failed") + break + case PasswordDialog.ChangePassword: + info = success ? qsTr("Password Changed Successfully") : qsTr("Password Change Failed") + break + case PasswordDialog.SetPassword: + info = success ? qsTr("Password Set Successfully") : qsTr("Password Set Failed") + passwdPushButton.text = success ? qsTr("Change Password") : qsTr("Set Password") + break + } + + msgDialog.openWithParameters(title,info, iconMode, StandardButton.Ok) + } + } + + MessageBox { + id: msgDialog + } + + function passwordClicked() { + if (ClientWrapper.accountAdaptor.hasPassword()){ + passwordDialog.openDialog(PasswordDialog.ChangePassword) + } else { + passwordDialog.openDialog(PasswordDialog.SetPassword) + } + } + + function delAccountSlot() { + deleteAccountDialog.open() + } + + DeleteAccountDialog{ + id: deleteAccountDialog + + anchors.centerIn: parent.Center + x: (parent.width - width) / 2 + y: (parent.height - height) / 2 + + onAccepted: { + ClientWrapper.accountAdaptor.setSelectedAccountId() + ClientWrapper.accountAdaptor.setSelectedConvId() + + if(ClientWrapper.utilsAdaptor.getAccountListSize() > 0){ + navigateToMainView() + } else { + navigateToNewWizardView() + } + } + } + + NameRegistrationDialog{ + id : nameRegistrationDialog + + onAccepted: { + registeredIdNeedsSet = false + } + } + + function slotRegisterName() { + refreshRelevantUI() + nameRegistrationDialog.openNameRegistrationDialog(registeredName) + } + + LinkDeviceDialog{ + id: linkDeviceDialog + + onAccepted: { + updateAndShowDevicesSlot() + } + } + + function showLinkDevSlot() { + linkDeviceDialog.openLinkDeviceDialog() + } + + RevokeDevicePasswordDialog{ + id: revokeDevicePasswordDialog + + onRevokeDeviceWithPassword:{ + revokeDeviceWithIDAndPassword(idOfDevice, password) + } + } + + MessageBox{ + id: revokeDeviceMessageBox + + property string idOfDev: "" + + title:qsTr("Remove Device") + text :qsTr("Are you sure you wish to remove this device?") + icon :StandardIcon.Information + standardButtons: StandardButton.Ok | StandardButton.Cancel + + onYes: { + accepted() + } + + onNo:{ + rejected() + } + + onDiscard: { + rejected() + } + + onAccepted: { + revokeDeviceWithIDAndPassword(idOfDev,"") + } + + onRejected: {} + } + + function removeDeviceSlot(index){ + var idOfDevice = deviceItemListModel.data(deviceItemListModel.index(index,0), DeviceItemListModel.DeviceID) + if(ClientWrapper.accountAdaptor.hasPassword()){ + revokeDevicePasswordDialog.openRevokeDeviceDialog(idOfDevice) + } else { + revokeDeviceMessageBox.idOfDev = idOfDevice + revokeDeviceMessageBox.open() + } + } + + function revokeDeviceWithIDAndPassword(idDevice, password){ + ClientWrapper.deviceModel.revokeDevice(idDevice, password) + updateAndShowDevicesSlot() + } + + function updateAndShowBannedContactsSlot() { + if(bannedListModel.rowCount() <= 0){ + bannedContactsLayoutWidget.visible = false + return + } + + bannedListModel.reset() + } + + function updateAndShowDevicesSlot() { + if(ClientWrapper.settingsAdaptor.getAccountConfig_Manageruri() === ""){ + linkDevPushButton.visible = true + } + + deviceItemListModel.reset() + } + + DeviceItemListModel { + id: deviceItemListModel + } + + BannedListModel{ + id: bannedListModel + } + + Layout.fillHeight: true + Layout.fillWidth: true + + ColumnLayout { + anchors.fill: parent + spacing: 0 + + Item { + Layout.fillWidth: true + + Layout.maximumHeight: 10 + Layout.minimumHeight: 10 + Layout.preferredHeight: 10 + + Layout.alignment: Qt.AlignTop + } + + RowLayout { + spacing: 6 + + Layout.alignment: Qt.AlignTop + + Layout.fillWidth: true + Layout.maximumHeight: 30 + Layout.minimumHeight: 30 + Layout.preferredHeight: accountPageTitle.height + + Item { + Layout.fillHeight: true + + Layout.maximumWidth: 30 + Layout.preferredWidth: 30 + Layout.minimumWidth: 30 + } + + Label { + id: accountPageTitle + + Layout.preferredWidth: 117 + + Layout.maximumHeight: 25 + Layout.preferredHeight: 25 + Layout.minimumHeight: 25 + + text: qsTr("Jami Account") + + font.pointSize: 15 + font.kerning: true + + horizontalAlignment: Text.AlignLeft + verticalAlignment: Text.AlignVCenter + } + + Item { + Layout.fillWidth: true + Layout.fillHeight: true + } + } + + ScrollView { + id: accoutScrollView + + property ScrollBar hScrollBar: ScrollBar.horizontal + property ScrollBar vScrollBar: ScrollBar.vertical + + Layout.fillHeight: true + Layout.fillWidth: true + + ScrollBar.horizontal.policy: ScrollBar.AsNeeded + ScrollBar.vertical.policy: ScrollBar.AsNeeded + + font.pointSize: 8 + font.kerning: true + clip: true + + ColumnLayout { + id: accoutnViewLayout + + Layout.fillHeight: true + Layout.maximumWidth: 625 + + Item { + Layout.fillHeight: true + + Layout.maximumWidth: 30 + Layout.preferredWidth: 30 + Layout.minimumWidth: 30 + } + + ColumnLayout { + spacing: 6 + Layout.fillHeight: true + Layout.fillWidth: true + + Layout.leftMargin: 30 + + Item { + Layout.fillHeight: true + + Layout.maximumWidth: 24 + Layout.preferredWidth: 24 + Layout.minimumWidth: 24 + } + + ToggleSwitch { + id: accountEnableCheckBox + + labelText: qsTr("Enable") + fontPointSize: 11 + + onSwitchToggled: { + setAccEnableSlot(checked) + } + } + + Item { + Layout.fillHeight: true + + Layout.maximumWidth: 20 + Layout.preferredWidth: 20 + Layout.minimumWidth: 20 + } + + ColumnLayout { + Layout.fillWidth: true + + Label { + Layout.fillWidth: true + + Layout.maximumHeight: 21 + Layout.preferredHeight: 21 + Layout.minimumHeight: 21 + + text: qsTr("Profile") + font.pointSize: 13 + font.kerning: true + + horizontalAlignment: Text.AlignLeft + verticalAlignment: Text.AlignVCenter + } + + Item { + Layout.fillWidth: true + + Layout.maximumHeight: 10 + Layout.preferredHeight: 10 + Layout.minimumHeight: 10 + } + + ColumnLayout { + Layout.fillWidth: true + layoutDirection: Qt.LeftToRight + + spacing: 6 + + PhotoboothView { + id: currentAccountAvatar + + Layout.alignment: Qt.AlignHCenter + + Layout.maximumWidth: 261 + Layout.preferredWidth: 261 + Layout.minimumWidth: 261 + Layout.maximumHeight: 261 + Layout.preferredHeight: 261 + Layout.minimumHeight: 261 + + Layout.leftMargin: 20 + + onImageAcquired: { + ClientWrapper.settingsAdaptor.setCurrAccAvatar(imgBase64) + } + + onImageCleared: { + ClientWrapper.settingsAdaptor.clearCurrentAvatar() + setAvatar() + } + } + + InfoLineEdit { + id: displayNameLineEdit + + fieldLayoutWidth: 261 + + Layout.leftMargin: 20 + + font.pointSize: 10 + font.kerning: true + + horizontalAlignment: Text.AlignHCenter + verticalAlignment: Text.AlignVCenter + + onEditingFinished: { + ClientWrapper.accountAdaptor.setCurrAccDisplayName( + displayNameLineEdit.text) + } + } + } + } + + Item { + Layout.fillHeight: true + + Layout.maximumWidth: 20 + Layout.preferredWidth: 20 + Layout.minimumWidth: 20 + } + + ColumnLayout { + Layout.fillWidth: true + + Label { + Layout.fillWidth: true + + Layout.maximumHeight: 21 + Layout.preferredHeight: 21 + Layout.minimumHeight: 21 + + text: qsTr("Identity") + font.pointSize: 13 + font.kerning: true + + horizontalAlignment: Text.AlignLeft + verticalAlignment: Text.AlignVCenter + } + + Item { + Layout.fillHeight: true + + Layout.maximumWidth: 10 + Layout.preferredWidth: 10 + Layout.minimumWidth: 10 + } + + ColumnLayout { + spacing: 7 + + Layout.fillWidth: true + + RowLayout { + spacing: 6 + Layout.fillWidth: true + Layout.maximumHeight: 30 + + Layout.leftMargin: 20 + + Layout.maximumWidth: 625 + + Label { + Layout.maximumWidth: 13 + Layout.preferredWidth: 13 + Layout.minimumWidth: 13 + + Layout.minimumHeight: 30 + Layout.preferredHeight: 30 + Layout.maximumHeight: 30 + + text: qsTr("Id") + font.pointSize: 10 + font.kerning: true + + horizontalAlignment: Text.AlignLeft + verticalAlignment: Text.AlignVCenter + } + + TextField { + id: currentRingID + + property var backgroundColor: "transparent" + property var borderColor: "transparent" + + Layout.fillWidth: true + + Layout.minimumHeight: 30 + Layout.preferredHeight: 30 + Layout.maximumHeight: 30 + + font.pointSize: 10 + font.kerning: true + font.bold: true + + readOnly: true + selectByMouse: true + + text: { refreshVariable + return ClientWrapper.settingsAdaptor.getCurrentAccount_Profile_Info_Uri()} + + horizontalAlignment: Text.AlignLeft + verticalAlignment: Text.AlignVCenter + + background: Rectangle { + anchors.fill: parent + radius: 0 + border.color: currentRingID.borderColor + border.width: 0 + color: currentRingID.backgroundColor + } + } + } + + RowLayout { + spacing: 6 + Layout.fillWidth: true + Layout.maximumHeight: 32 + + Layout.leftMargin: 20 + + layoutDirection: Qt.LeftToRight + + Label { + id: lblRegisteredName + + Layout.maximumWidth: 127 + Layout.preferredWidth: 127 + Layout.minimumWidth: 127 + + Layout.minimumHeight: 32 + Layout.preferredHeight: 32 + Layout.maximumHeight: 32 + + text: qsTr("Registered name") + + font.pointSize: 10 + font.kerning: true + + horizontalAlignment: Text.AlignLeft + verticalAlignment: Text.AlignVCenter + } + + RowLayout { + spacing: 6 + Layout.fillWidth: true + Layout.maximumHeight: 30 + Layout.alignment: Qt.AlignVCenter + + TextField { + id: currentRegisteredID + + Layout.maximumWidth: 300 + Layout.preferredWidth: 300 + Layout.minimumWidth: 300 + + Layout.minimumHeight: 30 + Layout.preferredHeight: 30 + Layout.maximumHeight: 30 + + placeholderText: { refreshVariable + var result = registeredIdNeedsSet ? qsTr("Type here to register a username") : "" + return result} + + text: { + refreshVariable + if (!registeredIdNeedsSet){ + return ClientWrapper.settingsAdaptor.get_CurrentAccountInfo_RegisteredName() + } else { + return "" + } + } + selectByMouse: true + readOnly: { refreshVariable + return !registeredIdNeedsSet} + + font.pointSize: 10 + font.kerning: true + font.bold: { refreshVariable + return !registeredIdNeedsSet} + + horizontalAlignment: Text.AlignLeft + verticalAlignment: Text.AlignVCenter + + background: Rectangle { + anchors.fill: parent + radius: {refreshVariable + var result = registeredIdNeedsSet ? height / 2 : 0 + return result} + border.color: "transparent" + border.width: {refreshVariable + var result = registeredIdNeedsSet ? 2 : 0 + return result} + color: {refreshVariable + var result = registeredIdNeedsSet ? Qt.rgba( + 240 / 256, 240 / 256, + 240 / 256, + 1.0) : "transparent" + return result} + } + + onTextEdited: { + verifyRegisteredNameSlot() + } + + onEditingFinished: { + verifyRegisteredNameSlot() + } + } + + LookupStatusLabel { + id: lookupStatusLabel + + visible:{refreshVariable + var result = registeredIdNeedsSet + && (regNameUi + !== CurrentAccountSettingsScrollPage.BLANK) + return result} + + MouseArea { + id: lookupStatusLabelArea + anchors.fill: parent + property bool isHovering: false + + onEntered: isHovering = true + onExited: isHovering = false + + hoverEnabled: true + } + + ToolTip.visible: lookupStatusLabelArea.isHovering + ToolTip.text: { + switch (regNameUi) { + case CurrentAccountSettingsScrollPage.BLANK: + return qsTr("") + case CurrentAccountSettingsScrollPage.INVALIDFORM: + return qsTr("A registered name should not have any spaces and must be at least three letters long") + case CurrentAccountSettingsScrollPage.TAKEN: + return qsTr("This name is already taken") + case CurrentAccountSettingsScrollPage.FREE: + return qsTr("Register this name") + case CurrentAccountSettingsScrollPage.SEARCHING: + return qsTr("") + default: + return qsTr("") + } + } + + lookupStatusState: { + switch (regNameUi) { + case CurrentAccountSettingsScrollPage.BLANK: + return "Blank" + case CurrentAccountSettingsScrollPage.INVALIDFORM: + return "Invalid" + case CurrentAccountSettingsScrollPage.TAKEN: + return "Taken" + case CurrentAccountSettingsScrollPage.FREE: + return "Free" + case CurrentAccountSettingsScrollPage.SEARCHING: + return "Searching" + default: + return "Blank" + } + } + } + + HoverableRadiusButton { + id: btnRegisterName + + visible: {refreshVariable + var result = registeredIdNeedsSet + && (regNameUi + === CurrentAccountSettingsScrollPage.FREE) + return result} + + Layout.maximumWidth: 80 + Layout.preferredWidth: 80 + Layout.minimumWidth: 80 + + Layout.minimumHeight: 30 + Layout.preferredHeight: 30 + Layout.maximumHeight: 30 + + text: qsTr("Register") + font.pointSize: 10 + font.kerning: true + + radius: height / 2 + } + + Item { + Layout.fillHeight: true + Layout.fillWidth: true + } + } + } + + RowLayout { + spacing: 6 + Layout.fillWidth: true + Layout.maximumHeight: 30 + + Layout.leftMargin: 20 + + HoverableButtonTextItem { + id: passwdPushButton + + visible: ClientWrapper.settingsAdaptor.getAccountConfig_Manageruri() === "" + + Layout.maximumWidth: 261 + Layout.preferredWidth: 261 + Layout.minimumWidth: 261 + + Layout.minimumHeight: 30 + Layout.preferredHeight: 30 + Layout.maximumHeight: 30 + text: ClientWrapper.accountAdaptor.hasPassword() ? qsTr("Change Password") : qsTr("Set Password") + + font.pointSize: 10 + font.kerning: true + + radius: height / 2 + + onClicked: { + passwordClicked() + } + } + + Item { + Layout.fillHeight: true + Layout.fillWidth: true + } + } + + RowLayout { + spacing: 6 + Layout.fillWidth: true + Layout.maximumHeight: 30 + + Layout.leftMargin: 20 + + HoverableButtonTextItem { + id: btnExportAccount + + visible: ClientWrapper.settingsAdaptor.getAccountConfig_Manageruri() === "" + + Layout.maximumWidth: 261 + Layout.preferredWidth: 261 + Layout.minimumWidth: 261 + + Layout.minimumHeight: 30 + Layout.preferredHeight: 30 + Layout.maximumHeight: 30 + + text: qsTr("Export Account") + font.pointSize: 10 + font.kerning: true + + radius: height / 2 + + onClicked: { + exportAccountSlot() + } + } + + Item { + Layout.fillHeight: true + Layout.fillWidth: true + } + } + + RowLayout { + spacing: 6 + Layout.fillWidth: true + Layout.maximumHeight: 30 + + Layout.leftMargin: 20 + + HoverableButtonTextItem { + id: btnDeletAccount + + backgroundColor: "red" + onEnterColor: Qt.rgba(150 / 256, 0, 0, 0.7) + onDisabledBackgroundColor: Qt.rgba( + 255 / 256, + 0, 0, 0.8) + onPressColor: backgroundColor + textColor: "white" + + Layout.maximumWidth: 261 + Layout.preferredWidth: 261 + Layout.minimumWidth: 261 + + Layout.minimumHeight: 30 + Layout.preferredHeight: 30 + Layout.maximumHeight: 30 + + text: qsTr("Delete Account") + font.pointSize: 10 + font.kerning: true + + radius: height / 2 + + onClicked: { + delAccountSlot() + } + } + + Item { + Layout.fillHeight: true + Layout.fillWidth: true + } + } + } + } + + Item { + Layout.fillWidth: true + + Layout.minimumHeight: 20 + Layout.preferredHeight: 20 + Layout.maximumHeight: 20 + } + + ColumnLayout { + Layout.fillWidth: true + + Label { + Layout.fillWidth: true + + Layout.maximumHeight: 27 + Layout.preferredHeight: 27 + Layout.minimumHeight: 27 + + text: qsTr("Linked Device") + font.pointSize: 13 + font.kerning: true + + horizontalAlignment: Text.AlignLeft + verticalAlignment: Text.AlignVCenter + } + + Item { + Layout.fillHeight: true + + Layout.maximumWidth: 10 + Layout.preferredWidth: 10 + Layout.minimumWidth: 10 + } + + ColumnLayout { + spacing: 7 + + Layout.fillWidth: true + + ListViewJami { + id: settingsListView + + Layout.leftMargin: 20 + + Layout.fillWidth: true + + Layout.minimumWidth: 580 + Layout.preferredWidth: 605 + + Layout.minimumHeight: 164 + Layout.preferredHeight: 164 + Layout.maximumHeight: 164 + + model: deviceItemListModel + + delegate: DeviceItemDelegate{ + id: settingsListDelegate + + width: settingsListView.width + height: 85 + + deviceName : DeviceName + deviceId: DeviceID + isCurrent: IsCurrent + + onClicked: { + settingsListView.currentIndex = index + } + + onBtnRemoveDeviceClicked:{ + removeDeviceSlot(index) + } + } + } + + HoverableRadiusButton { + id: linkDevPushButton + + visible: ClientWrapper.settingsAdaptor.getAccountConfig_Manageruri() === "" + + Layout.leftMargin: 20 + + Layout.fillWidth: true + + Layout.maximumHeight: 30 + Layout.preferredHeight: 30 + Layout.minimumHeight: 30 + + radius: height / 2 + + text: qsTr("+Link Another Device") + font.pointSize: 10 + font.kerning: true + + onClicked: { + showLinkDevSlot() + } + } + } + } + + Item { + Layout.fillWidth: true + + Layout.minimumHeight: 20 + Layout.preferredHeight: 20 + Layout.maximumHeight: 20 + } + + // banned list view + ColumnLayout { + id: bannedContactsLayoutWidget + + Layout.fillWidth: true + spacing: 6 + + RowLayout { + Layout.leftMargin: 9 + Layout.rightMargin: 8 + Layout.topMargin: 1 + + Layout.fillWidth: true + Layout.maximumHeight: 30 + + Label { + Layout.preferredWidth: 164 + Layout.minimumWidth: 164 + + Layout.minimumHeight: 30 + Layout.preferredHeight: 30 + Layout.maximumHeight: 30 + + text: qsTr("Banned Contact") + font.pointSize: 13 + font.kerning: true + + horizontalAlignment: Text.AlignLeft + verticalAlignment: Text.AlignVCenter + } + + Item { + Layout.fillHeight: true + + Layout.maximumWidth: 10 + Layout.preferredWidth: 10 + Layout.minimumWidth: 10 + } + + HoverableRadiusButton { + id: bannedContactsBtn + + Layout.maximumWidth: 30 + Layout.preferredWidth: 30 + Layout.minimumWidth: 30 + + Layout.minimumHeight: 30 + Layout.preferredHeight: 30 + Layout.maximumHeight: 30 + + buttonImageHeight: height + buttonImageWidth: height + + radius: height / 2 + + icon.source: bannedContactsListWidget.visible? "qrc:/images/icons/round-arrow_drop_up-24px.svg" : "qrc:/images/icons/round-arrow_drop_down-24px.svg" + icon.height: 32 + icon.width: 32 + + onClicked: { + toggleBannedContacts() + } + } + + Item { + Layout.fillHeight: true + Layout.fillWidth: true + } + } + + ColumnLayout { + id: bannedContactsListWidget + + spacing: 6 + + Layout.leftMargin: 9 + Layout.rightMargin: 8 + Layout.bottomMargin: 9 + Item { + Layout.fillWidth: true + + Layout.minimumHeight: 10 + Layout.preferredHeight: 10 + Layout.maximumHeight: 10 + } + + ListViewJami { + id: bannedListWidget + + Layout.leftMargin: 20 + Layout.fillWidth: true + + Layout.minimumWidth: 580 + + Layout.minimumHeight: 150 + Layout.preferredHeight: 150 + Layout.maximumHeight: 150 + + model: bannedListModel + + delegate: BannedItemDelegate{ + id: bannedListDelegate + + width: bannedListWidget.width + height: 74 + + contactName : ContactName + contactID: ContactID + contactPicture_base64: ContactPicture + + onClicked: { + bannedListWidget.currentIndex = index + } + + onBtnReAddContactClicked: { + unban(index) + } + } + } + } + } + + Item { + Layout.fillWidth: true + + Layout.minimumHeight: 20 + Layout.preferredHeight: 20 + Layout.maximumHeight: 20 + } + + RowLayout { + Layout.fillWidth: true + + Layout.minimumHeight: 30 + Layout.preferredHeight: 30 + Layout.maximumHeight: 30 + + Item { + Layout.fillWidth: true + Layout.fillHeight: true + } + + HoverableRadiusButton { + id: advancedAccountSettingsPButton + + Layout.minimumWidth: 180 + + Layout.minimumHeight: 30 + Layout.preferredHeight: 30 + Layout.maximumHeight: 30 + + radius: height / 2 + + text: qsTr("Advanced Account Settings") + font.pointSize: 10 + font.kerning: true + + icon.source: { + if (advanceSettingsView.visible) { + return "qrc:/images/icons/round-arrow_drop_up-24px.svg" + } else { + return "qrc:/images/icons/round-arrow_drop_down-24px.svg" + } + } + + icon.height: 24 + icon.width: 24 + + onClicked: { + advanceSettingsView.visible = !advanceSettingsView.visible + if (advanceSettingsView.visible) { + advanceSettingsView.updateAccountInfoDisplayedAdvance() + var mappedCoor = advancedAccountSettingsPButton.mapToItem(accoutnViewLayout,advancedAccountSettingsPButton.x,advancedAccountSettingsPButton.y) + accoutScrollView.vScrollBar.position = mappedCoor.y / accoutnViewLayout.height + } else { + accoutScrollView.vScrollBar.position = 0 + } + } + } + + Item { + Layout.fillWidth: true + Layout.fillHeight: true + } + } + } + + Item { + Layout.fillWidth: true + + Layout.minimumHeight: 48 + Layout.preferredHeight: 48 + Layout.maximumHeight: 48 + } + + ColumnLayout { + spacing: 6 + Layout.fillHeight: true + Layout.fillWidth: true + + Layout.leftMargin: 30 + + // instantiate advance setting page + AdvancedSettingsView { + id: advanceSettingsView + + Layout.leftMargin: 10 + visible: false + } + } + } + } + + Item { + Layout.fillHeight: true + Layout.fillWidth: true + } + } +} diff --git a/src/settingsview/components/CurrentSIPAccountSettingScrollPage.qml b/src/settingsview/components/CurrentSIPAccountSettingScrollPage.qml new file mode 100644 index 00000000..b5d1d2c0 --- /dev/null +++ b/src/settingsview/components/CurrentSIPAccountSettingScrollPage.qml @@ -0,0 +1,633 @@ +/* + * Copyright (C) 2019-2020 by Savoir-faire Linux + * Author: Yang Wang + * + * 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 . + */ + +import QtQuick 2.15 +import QtQuick.Window 2.14 +import QtQuick.Controls 2.14 +import QtQuick.Controls.Universal 2.12 +import QtQuick.Layouts 1.3 +import QtGraphicalEffects 1.14 +import net.jami.Models 1.0 + +import "../../commoncomponents" + +Rectangle { + signal navigateToMainView + signal navigateToNewWizardView + + function updateAccountInfoDisplayed() { + displaySIPNameLineEdit.text = ClientWrapper.settingsAdaptor.getCurrentAccount_Profile_Info_Alias() + usernameSIP.text = ClientWrapper.settingsAdaptor.getAccountConfig_Username() + hostnameSIP.text = ClientWrapper.settingsAdaptor.getAccountConfig_Hostname() + passSIPlineEdit.text = ClientWrapper.settingsAdaptor.getAccountConfig_Password() + proxySIP.text = ClientWrapper.settingsAdaptor.getAccountConfig_ProxyServer() + + accountSIPEnableCheckBox.checked = ClientWrapper.settingsAdaptor.get_CurrentAccountInfo_Enabled() + + setAvatar() + + if (advanceSIPSettingsView.visible) { + advanceSIPSettingsView.updateAccountInfoDisplayedAdvanceSIP() + } + } + + function isPhotoBoothOpened() { + return currentSIPAccountAvatar.takePhotoState + } + + function setAvatar() { + currentSIPAccountAvatar.setAvatarPixmap( + ClientWrapper.settingsAdaptor.getAvatarImage_Base64( + currentSIPAccountAvatar.boothWidht), + ClientWrapper.settingsAdaptor.getIsDefaultAvatar()) + } + + function stopBooth() { + currentSIPAccountAvatar.stopBooth() + } + + // slots + function setAccEnableSlot(state) { + ClientWrapper.accountModel.setAccountEnabled(ClientWrapper.utilsAdaptor.getCurrAccId(), state) + } + + function delAccountSlot() { + deleteAccountDialog_SIP.open() + } + + DeleteAccountDialog{ + id: deleteAccountDialog_SIP + + anchors.centerIn: parent.Center + x: (parent.width - width) / 2 + y: (parent.height - height) / 2 + + onAccepted: { + ClientWrapper.accountAdaptor.setSelectedAccountId() + ClientWrapper.accountAdaptor.setSelectedConvId() + + if(ClientWrapper.utilsAdaptor.getAccountListSize() > 0){ + navigateToMainView() + } else { + navigateToNewWizardView() + } + } + } + + Layout.fillHeight: true + Layout.fillWidth: true + + ColumnLayout { + anchors.fill: parent + spacing: 0 + + Item { + Layout.fillWidth: true + + Layout.maximumHeight: 10 + Layout.minimumHeight: 10 + Layout.preferredHeight: 10 + + Layout.alignment: Qt.AlignTop + } + + RowLayout { + spacing: 6 + + Layout.alignment: Qt.AlignTop + + Layout.fillWidth: true + Layout.maximumHeight: 31 + Layout.minimumHeight: 0 + Layout.preferredHeight: accountPageTitleSIP.height + + Item { + Layout.fillHeight: true + + Layout.maximumWidth: 48 + Layout.preferredWidth: 48 + Layout.minimumWidth: 48 + } + + Label { + id: accountPageTitleSIP + + Layout.preferredWidth: 133 + + Layout.preferredHeight: 31 + Layout.minimumHeight: 25 + + text: qsTr("SIP Account") + + font.pointSize: 15 + font.kerning: true + + horizontalAlignment: Text.AlignLeft + verticalAlignment: Text.AlignVCenter + } + + Item { + Layout.fillWidth: true + Layout.fillHeight: true + } + } + + ScrollView { + id: accountSIPScrollView + + property ScrollBar hScrollBar: ScrollBar.horizontal + property ScrollBar vScrollBar: ScrollBar.vertical + + Layout.fillHeight: true + Layout.fillWidth: true + + ScrollBar.horizontal.policy: ScrollBar.AsNeeded + ScrollBar.vertical.policy: ScrollBar.AsNeeded + + font.pointSize: 8 + font.kerning: true + clip: true + + ColumnLayout { + id: accountSIPLayout + + Layout.fillHeight: true + Layout.maximumWidth: 598 + + Item { + Layout.fillHeight: true + + Layout.maximumWidth: 30 + Layout.preferredWidth: 30 + Layout.minimumWidth: 30 + } + + ColumnLayout { + spacing: 6 + Layout.fillHeight: true + Layout.fillWidth: true + + Layout.leftMargin: 48 + + Item { + Layout.fillHeight: true + + Layout.maximumWidth: 24 + Layout.preferredWidth: 24 + Layout.minimumWidth: 24 + } + + ToggleSwitch { + id: accountSIPEnableCheckBox + + labelText: qsTr("Enable") + fontPointSize: 10 + + onSwitchToggled: { + setAccEnableSlot(checked) + } + } + + Item { + Layout.fillHeight: true + + Layout.maximumWidth: 20 + Layout.preferredWidth: 20 + Layout.minimumWidth: 20 + } + + ColumnLayout { + Layout.fillWidth: true + + Label { + Layout.fillWidth: true + + Layout.maximumHeight: 21 + Layout.preferredHeight: 21 + Layout.minimumHeight: 21 + + text: qsTr("Profile") + font.pointSize: 13 + font.kerning: true + + horizontalAlignment: Text.AlignLeft + verticalAlignment: Text.AlignVCenter + } + + Item { + Layout.fillWidth: true + + Layout.maximumHeight: 10 + Layout.preferredHeight: 10 + Layout.minimumHeight: 10 + } + + ColumnLayout { + Layout.fillWidth: true + layoutDirection: Qt.LeftToRight + + spacing: 6 + + PhotoboothView { + id: currentSIPAccountAvatar + + Layout.alignment: Qt.AlignHCenter + + Layout.maximumWidth: 261 + Layout.preferredWidth: 261 + Layout.minimumWidth: 261 + Layout.maximumHeight: 261 + Layout.preferredHeight: 261 + Layout.minimumHeight: 261 + + Layout.leftMargin: 20 + + onImageAcquired: { + ClientWrapper.settingsAdaptor.setCurrAccAvatar(imgBase64) + } + + onImageCleared: { + ClientWrapper.settingsAdaptor.clearCurrentAvatar() + setAvatar() + } + } + + InfoLineEdit { + id: displaySIPNameLineEdit + + fieldLayoutWidth: 261 + + Layout.leftMargin: 20 + + font.pointSize: 10 + font.kerning: true + + horizontalAlignment: Text.AlignHCenter + verticalAlignment: Text.AlignVCenter + + onEditingFinished: { + ClientWrapper.accountAdaptor.setCurrAccDisplayName( + displaySIPNameLineEdit.text) + } + } + } + } + + Item { + Layout.fillWidth: true + + Layout.maximumHeight: 20 + Layout.preferredHeight: 20 + Layout.minimumHeight: 20 + } + + ColumnLayout { + Layout.fillWidth: true + spacing: 6 + + Label { + Layout.fillWidth: true + + Layout.maximumHeight: 27 + Layout.preferredHeight: 27 + Layout.minimumHeight: 27 + + text: qsTr("Identity") + font.pointSize: 13 + font.kerning: true + + horizontalAlignment: Text.AlignLeft + verticalAlignment: Text.AlignVCenter + } + + Item { + Layout.fillWidth: true + + Layout.maximumHeight: 10 + Layout.preferredHeight: 10 + Layout.minimumHeight: 10 + } + + ColumnLayout { + Layout.fillWidth: true + spacing: 6 + + GridLayout { + rows: 4 + columns: 2 + flow: GridLayout.LeftToRight + rowSpacing: 14 + columnSpacing: 6 + + Layout.fillWidth: true + + Layout.leftMargin: 20 + + // user name + Label { + Layout.maximumWidth: 76 + Layout.preferredWidth: 76 + Layout.minimumWidth: 76 + + Layout.maximumHeight: 30 + Layout.preferredHeight: 30 + Layout.minimumHeight: 30 + + text: qsTr("Username") + font.pointSize: 10 + font.kerning: true + + horizontalAlignment: Text.AlignLeft + verticalAlignment: Text.AlignVCenter + } + + InfoLineEdit { + id: usernameSIP + + fieldLayoutWidth: 300 + + font.pointSize: 10 + font.kerning: true + + horizontalAlignment: Text.AlignLeft + verticalAlignment: Text.AlignVCenter + + onEditingFinished: { + ClientWrapper.settingsAdaptor.setAccountConfig_Username( + usernameSIP.text) + } + } + + // host name + Label { + Layout.maximumWidth: 76 + Layout.preferredWidth: 76 + Layout.minimumWidth: 76 + + Layout.maximumHeight: 30 + Layout.preferredHeight: 30 + Layout.minimumHeight: 30 + + text: qsTr("Hostname") + font.pointSize: 10 + font.kerning: true + + horizontalAlignment: Text.AlignLeft + verticalAlignment: Text.AlignVCenter + } + + InfoLineEdit { + id: hostnameSIP + + fieldLayoutWidth: 300 + + font.pointSize: 10 + font.kerning: true + + horizontalAlignment: Text.AlignLeft + verticalAlignment: Text.AlignVCenter + + onEditingFinished: { + ClientWrapper.settingsAdaptor.setAccountConfig_Hostname( + hostnameSIP.text) + } + } + + // proxy + Label { + Layout.maximumWidth: 76 + Layout.preferredWidth: 76 + Layout.minimumWidth: 76 + + Layout.maximumHeight: 30 + Layout.preferredHeight: 30 + Layout.minimumHeight: 30 + + text: qsTr("Proxy") + font.pointSize: 10 + font.kerning: true + + horizontalAlignment: Text.AlignLeft + verticalAlignment: Text.AlignVCenter + } + + InfoLineEdit { + id: proxySIP + + fieldLayoutWidth: 300 + + font.pointSize: 10 + font.kerning: true + + horizontalAlignment: Text.AlignLeft + verticalAlignment: Text.AlignVCenter + + onEditingFinished: { + ClientWrapper.settingsAdaptor.setAccountConfig_ProxyServer( + proxySIP.text) + } + } + + // password + Label { + Layout.maximumWidth: 76 + Layout.preferredWidth: 76 + Layout.minimumWidth: 76 + + Layout.maximumHeight: 30 + Layout.preferredHeight: 30 + Layout.minimumHeight: 30 + + text: qsTr("Password") + font.pointSize: 10 + font.kerning: true + + horizontalAlignment: Text.AlignLeft + verticalAlignment: Text.AlignVCenter + } + + InfoLineEdit { + id: passSIPlineEdit + + fieldLayoutWidth: 300 + + font.pointSize: 10 + font.kerning: true + + echoMode: TextInput.Password + horizontalAlignment: Text.AlignLeft + verticalAlignment: Text.AlignVCenter + + onEditingFinished: { + ClientWrapper.settingsAdaptor.setAccountConfig_Password( + passSIPlineEdit.text) + } + } + } + + Item { + Layout.fillWidth: true + + Layout.maximumHeight: 10 + Layout.preferredHeight: 10 + Layout.minimumHeight: 10 + } + + RowLayout { + Layout.fillWidth: true + Layout.maximumHeight: 30 + Layout.leftMargin: 20 + + HoverableButtonTextItem { + id: btnSIPDeletAccount + + backgroundColor: "red" + onEnterColor: Qt.rgba(150 / 256, 0, 0, 0.7) + onDisabledBackgroundColor: Qt.rgba( + 255 / 256, + 0, 0, 0.8) + onPressColor: backgroundColor + textColor: "white" + + Layout.maximumWidth: 261 + Layout.preferredWidth: 261 + Layout.minimumWidth: 261 + + Layout.maximumHeight: 30 + Layout.preferredHeight: 30 + Layout.minimumHeight: 30 + + radius: height / 2 + + text: qsTr("Delete Account") + font.pointSize: 10 + font.kerning: true + + onClicked: { + delAccountSlot() + } + } + + Item { + Layout.fillHeight: true + Layout.fillWidth: true + } + } + } + } + + Item { + Layout.fillWidth: true + + Layout.maximumHeight: 40 + Layout.preferredHeight: 40 + Layout.minimumHeight: 40 + } + + RowLayout { + Layout.fillWidth: true + + Layout.minimumHeight: 30 + Layout.preferredHeight: 30 + Layout.maximumHeight: 30 + + Layout.minimumWidth: 598 + Layout.preferredWidth: 598 + + Item { + Layout.fillWidth: true + Layout.fillHeight: true + } + + HoverableRadiusButton { + id: advancedAccountSettingsSIPButton + + Layout.minimumWidth: 180 + + Layout.minimumHeight: 30 + Layout.preferredHeight: 30 + Layout.maximumHeight: 30 + + radius: height / 2 + + text: qsTr("Advanced Account Settings") + font.pointSize: 10 + font.kerning: true + + icon.source: { + if (advanceSIPSettingsView.visible) { + return "qrc:/images/icons/round-arrow_drop_up-24px.svg" + } else { + return "qrc:/images/icons/round-arrow_drop_down-24px.svg" + } + } + + icon.height: 24 + icon.width: 24 + + onClicked: { + advanceSIPSettingsView.visible = !advanceSIPSettingsView.visible + if(advanceSIPSettingsView.visible){ + advanceSIPSettingsView.updateAccountInfoDisplayedAdvanceSIP() + var coor = advancedAccountSettingsSIPButton.mapToItem(accountSIPLayout,advancedAccountSettingsSIPButton.x,advancedAccountSettingsSIPButton.y) + accountSIPScrollView.vScrollBar.position = coor.y / accountSIPLayout.height + } else { + accountSIPScrollView.vScrollBar.position = 0 + } + } + } + + Item { + Layout.fillWidth: true + Layout.fillHeight: true + } + } + } + + Item { + Layout.fillWidth: true + + Layout.minimumHeight: 48 + Layout.preferredHeight: 48 + Layout.maximumHeight: 48 + } + + ColumnLayout { + spacing: 6 + Layout.fillHeight: true + Layout.fillWidth: true + + Layout.leftMargin: 30 + + // instantiate advance setting page + AdvancedSIPSettingsView { + id: advanceSIPSettingsView + + Layout.leftMargin: 10 + visible: false + } + } + } + } + + Item { + Layout.fillHeight: true + Layout.fillWidth: true + } + } +} diff --git a/src/settingsview/components/DeviceItemDelegate.qml b/src/settingsview/components/DeviceItemDelegate.qml new file mode 100644 index 00000000..f2502610 --- /dev/null +++ b/src/settingsview/components/DeviceItemDelegate.qml @@ -0,0 +1,220 @@ +/* + * Copyright (C) 2019-2020 by Savoir-faire Linux + * Author: Yang Wang + * + * 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 . + */ + +import QtQuick 2.15 +import QtQuick.Window 2.15 +import QtQuick.Controls 2.15 +import QtQuick.Controls.Universal 2.12 +import QtQuick.Layouts 1.3 +import QtGraphicalEffects 1.14 +import QtQuick.Controls.Styles 1.4 +import net.jami.Models 1.0 + +import "../../commoncomponents" + +ItemDelegate { + id: deviceItemDelegate + + property string deviceName : "" + property string deviceId: "" + property bool isCurrent : false + + property bool editable : false + + signal btnRemoveDeviceClicked + + function btnEditDeviceEnter(){ + btnEditDevice.enterBtn() + } + + function btnEditDeviceExit(){ + btnEditDevice.exitBtn() + } + + function btnEditPress(){ + btnEditDevice.pressBtn() + } + + function btnEditRelease(){ + btnEditDevice.releaseBtn() + } + + function toggleEditable(){ + editable = !editable + if(editable){ + ClientWrapper.settingsAdaptor.setDeviceName(editDeviceName.text) + } + } + + highlighted: ListView.isCurrentItem + + RowLayout{ + anchors.fill: parent + + spacing: 7 + + Label{ + Layout.leftMargin: 7 + Layout.topMargin: 7 + Layout.bottomMargin: 7 + + Layout.minimumWidth: 30 + Layout.preferredWidth: 30 + Layout.maximumWidth: 30 + + Layout.minimumHeight: 30 + Layout.preferredHeight: 30 + Layout.maximumHeight: 30 + + background: Rectangle{ + anchors.fill: parent + Image { + anchors.fill: parent + source: "qrc:/images/icons/baseline-desktop_windows-24px.svg" + } + } + } + + ColumnLayout{ + Layout.fillWidth: true + Layout.fillHeight: true + + Layout.topMargin: 7 + Layout.bottomMargin: 7 + + InfoLineEdit{ + id: editDeviceName + + Layout.fillWidth: true + Layout.minimumWidth: 0 + Layout.maximumWidth: 16777215 + + Layout.minimumHeight: 30 + Layout.preferredHeight: 30 + Layout.maximumHeight: 30 + + font.pointSize: 8 + font.kerning: true + + horizontalAlignment: Text.AlignLeft + verticalAlignment: Text.AlignVCenter + + readOnly: !editable + + text: deviceName + } + + RowLayout{ + Layout.maximumWidth: editDeviceName.fieldLayoutWidth + + Layout.minimumHeight: 30 + + Label{ + id: labelDeviceId + + //Layout.minimumWidth: 71 + Layout.minimumHeight: 30 + + font.pointSize: 8 + font.kerning: true + text: deviceId === "" ? qsTr("Device Id") : deviceId + } + + Item{ + Layout.fillWidth: true + + Layout.minimumWidth: 0 + Layout.minimumHeight: 20 + } + + Label{ + id: labelThisDevice + + //Layout.minimumWidth: 80 + Layout.minimumHeight: 30 + + visible: isCurrent + + font.pointSize: 8 + font.kerning: true + font.italic: true + color: "green" + text: qsTr("this device") + } + } + } + + HoverableRadiusButton{ + id: btnEditDevice + + Layout.topMargin: 7 + Layout.bottomMargin: 7 + + Layout.minimumWidth: 30 + Layout.preferredWidth: 30 + Layout.maximumWidth: 30 + + Layout.minimumHeight: 30 + Layout.preferredHeight: 30 + Layout.maximumHeight: 30 + + buttonImageHeight: height + buttonImageWidth: height + + source:{ + if(isCurrent) { + var path = editable ? "qrc:/images/icons/round-edit-24px.svg" : "qrc:/images/icons/round-save_alt-24px.svg" + return path + } else { + return "qrc:/images/icons/round-remove_circle-24px.svg" + } + } + + ToolTip.visible: isHovering + ToolTip.text: { + if(isCurrent) { + if(editable){ + return qsTr("Edit Device Name") + } else { + return qsTr("Save new device name") + } + } else { + return qsTr("Unlink Device From Account") + } + } + + onClicked: { + if(isCurrent) { + toggleEditable() + } else { + btnRemoveDeviceClicked() + } + } + } + + Item{ + Layout.rightMargin: 7 + + Layout.minimumWidth: 8 + Layout.preferredWidth: 8 + Layout.maximumWidth: 8 + + Layout.minimumHeight: 20 + } + } +} diff --git a/src/settingsview/components/GeneralSettingsPage.qml b/src/settingsview/components/GeneralSettingsPage.qml new file mode 100644 index 00000000..72eb4d19 --- /dev/null +++ b/src/settingsview/components/GeneralSettingsPage.qml @@ -0,0 +1,678 @@ +/* + * Copyright (C) 2019-2020 by Savoir-faire Linux + * Author: Yang Wang + * + * 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 . + */ + +import QtQuick 2.15 +import QtQuick.Window 2.14 +import QtQuick.Controls 2.14 +import QtQuick.Controls.Universal 2.12 +import QtQuick.Layouts 1.3 +import Qt.labs.platform 1.1 +import QtGraphicalEffects 1.14 +import net.jami.Models 1.0 +import "../../commoncomponents" + +Rectangle { + id: generalSettingsRect + + function populateGeneralSettings(){ + // settings + closeOrMinCheckBox.checked = ClientWrapper.settingsAdaptor.getSettingsValue_CloseOrMinimized() + applicationOnStartUpCheckBox.checked = ClientWrapper.utilsAdaptor.checkStartupLink() + notificationCheckBox.checked = ClientWrapper.settingsAdaptor.getSettingsValue_EnableNotifications() + + alwaysRecordingCheckBox.checked = ClientWrapper.avmodel.getAlwaysRecord() + recordPreviewCheckBox.checked = ClientWrapper.avmodel.getRecordPreview() + recordQualityValueLabel.text = ClientWrapper.utilsAdaptor.getRecordQualityString(ClientWrapper.avmodel.getRecordQuality() / 100) + recordQualitySlider.value = ClientWrapper.avmodel.getRecordQuality() / 100 + + ClientWrapper.avmodel.setRecordPath(ClientWrapper.settingsAdaptor.getDir_Document()) + + autoUpdateCheckBox.checked = ClientWrapper.settingsAdaptor.getSettingsValue_AutoUpdate() + } + + function slotSetNotifications(state){ + ClientWrapper.settingsAdaptor.setNotifications(state) + } + + function slotSetClosedOrMin(state){ + ClientWrapper.settingsAdaptor.setClosedOrMin(state) + } + + function slotSetRunOnStartUp(state){ + ClientWrapper.settingsAdaptor.setRunOnStartUp(state) + } + + function slotSetUpdateAutomatic(state){ + ClientWrapper.settingsAdaptor.setUpdateAutomatic(state) + } + + function slotAlwaysRecordingClicked(state){ + ClientWrapper.avmodel.setAlwaysRecord(state) + } + + function slotRecordPreviewClicked(state){ + ClientWrapper.avmodel.setRecordPreview(state) + } + + function slotRecordQualitySliderValueChanged(value){ + recordQualityValueLabel.text = ClientWrapper.utilsAdaptor.getRecordQualityString(value) + updateRecordQualityTimer.restart() + } + + Timer{ + id: updateRecordQualityTimer + + interval: 500 + + onTriggered: { + slotRecordQualitySliderSliderReleased() + } + } + + function slotRecordQualitySliderSliderReleased(){ + var value = recordQualitySlider.value + ClientWrapper.avmodel.setRecordQuality(value * 100) + } + + function openDownloadFolderSlot(){ + downloadPathDialog.open() + } + + FolderDialog { + id: downloadPathDialog + + title: qsTr("Select A Folder For Your Downloads") + currentFolder: StandardPaths.writableLocation(StandardPaths.DownloadLocation) + + onAccepted: { + var dir = ClientWrapper.utilsAdaptor.getAbsPath(folder.toString()) + downloadPath = dir + } + + onRejected: {} + + onVisibleChanged: { + if (!visible) { + rejected() + } + } + } + + function openRecordFolderSlot(){ + recordPathDialog.open() + } + + FolderDialog { + id: recordPathDialog + + title: qsTr("Select A Folder For Your Recordings") + currentFolder: StandardPaths.writableLocation(StandardPaths.HomeLocation) + + onAccepted: { + var dir = ClientWrapper.utilsAdaptor.getAbsPath(folder.toString()) + recordPath = dir + } + + onRejected: {} + + onVisibleChanged: { + if (!visible) { + rejected() + } + } + } + + //TODO: complete check for update and check for Beta slot functions + function checkForUpdateSlot(){} + function installBetaSlot(){} + + // settings + property string downloadPath: ClientWrapper.settingsAdaptor.getDir_Download() + + // recording + //property AVModel avmodel: ClientWrapper.accountAdaptor.avModel() + property string recordPath: ClientWrapper.settingsAdaptor.getDir_Document() + + onDownloadPathChanged: { + if(downloadPath === "") return + ClientWrapper.settingsAdaptor.setDownloadPath(downloadPath) + } + + onRecordPathChanged: { + if(recordPath === "") return + + if(ClientWrapper.avmodel){ + ClientWrapper.avmodel.setRecordPath(recordPath) + } + } + + Layout.fillHeight: true + Layout.fillWidth: true + + ScrollView{ + anchors.fill: parent + clip: true + + RowLayout { + width: generalSettingsRect.width + height: generalSettingsRect.height + + spacing: 0 + + Item { + Layout.fillHeight: true + Layout.maximumWidth: 48 + Layout.preferredWidth: 48 + Layout.minimumWidth: 48 + } + + ColumnLayout { + spacing: 6 + + Layout.fillHeight: true + Layout.maximumWidth: 580 + Layout.preferredWidth: 580 + Layout.minimumWidth: 580 + + Item { + Layout.fillWidth: true + Layout.minimumHeight: 10 + Layout.preferredHeight: 10 + Layout.maximumHeight: 10 + } + + Label { + Layout.fillWidth: true + Layout.minimumHeight: 25 + Layout.preferredHeight: 25 + Layout.maximumHeight: 25 + + text: qsTr("General") + font.pointSize: 15 + font.kerning: true + + horizontalAlignment: Text.AlignLeft + verticalAlignment: Text.AlignVCenter + } + + Item { + Layout.fillWidth: true + Layout.minimumHeight: 24 + Layout.preferredHeight: 24 + Layout.maximumHeight: 24 + } + + // system setting panel + ColumnLayout { + spacing: 6 + Layout.fillWidth: true + + Label { + Layout.fillWidth: true + Layout.minimumHeight: 21 + Layout.preferredHeight: 21 + Layout.maximumHeight: 21 + + text: qsTr("System") + font.pointSize: 13 + font.kerning: true + + horizontalAlignment: Text.AlignLeft + verticalAlignment: Text.AlignVCenter + } + + Item { + Layout.fillWidth: true + + Layout.minimumHeight: 10 + Layout.preferredHeight: 10 + Layout.maximumHeight: 10 + } + + ColumnLayout { + spacing: 6 + Layout.fillWidth: true + + ToggleSwitch { + id: notificationCheckBox + + Layout.leftMargin: 20 + + labelText: "Enable desktop notifications" + fontPointSize: 11 + + onSwitchToggled: { + slotSetNotifications(checked) + } + } + + ToggleSwitch { + id: closeOrMinCheckBox + + Layout.leftMargin: 20 + + labelText: "Keep minimize on close" + fontPointSize: 11 + + onSwitchToggled: { + slotSetClosedOrMin(checked) + } + } + + ToggleSwitch { + id: applicationOnStartUpCheckBox + + Layout.leftMargin: 20 + + labelText: "Run on Startup" + fontPointSize: 11 + + onSwitchToggled: { + slotSetRunOnStartUp(checked) + } + } + + RowLayout { + spacing: 6 + + Layout.leftMargin: 20 + Layout.fillWidth: true + Layout.maximumHeight: 30 + + Label { + Layout.fillHeight: true + + Layout.maximumWidth: 94 + Layout.preferredWidth: 94 + Layout.minimumWidth: 94 + + text: qsTr("Download folder") + font.pointSize: 10 + font.kerning: true + + horizontalAlignment: Text.AlignLeft + verticalAlignment: Text.AlignVCenter + } + + Item { + Layout.fillHeight: true + Layout.fillWidth: true + } + + HoverableRadiusButton { + id: downloadButton + + Layout.maximumWidth: 320 + Layout.preferredWidth: 320 + Layout.minimumWidth: 320 + + Layout.minimumHeight: 30 + Layout.preferredHeight: 30 + Layout.maximumHeight: 30 + + radius: height / 2 + + icon.source: "qrc:/images/icons/round-folder-24px.svg" + icon.height: 24 + icon.width: 24 + + text: downloadPath + fontPointSize: 10 + + onClicked: { + openDownloadFolderSlot() + } + } + } + } + } + + Item { + Layout.fillWidth: true + Layout.minimumHeight: 20 + Layout.preferredHeight: 20 + Layout.maximumHeight: 20 + } + + // call recording setting panel + ColumnLayout { + spacing: 6 + Layout.fillWidth: true + + Label { + Layout.fillWidth: true + Layout.minimumHeight: 21 + Layout.preferredHeight: 21 + Layout.maximumHeight: 21 + + text: qsTr("Call Recording") + font.pointSize: 13 + font.kerning: true + + horizontalAlignment: Text.AlignLeft + verticalAlignment: Text.AlignVCenter + } + + Item { + Layout.fillWidth: true + + Layout.minimumHeight: 10 + Layout.preferredHeight: 10 + Layout.maximumHeight: 10 + } + + ColumnLayout { + spacing: 6 + Layout.fillWidth: true + + ToggleSwitch { + id: alwaysRecordingCheckBox + + Layout.leftMargin: 20 + + labelText: "Always record calls" + fontPointSize: 11 + + onSwitchToggled: { + slotAlwaysRecordingClicked(checked) + } + } + + ToggleSwitch { + id: recordPreviewCheckBox + + Layout.leftMargin: 20 + + labelText: "Record preview video for a call" + fontPointSize: 11 + + onSwitchToggled: { + slotRecordPreviewClicked(checked) + } + } + + RowLayout { + spacing: 6 + Layout.leftMargin: 20 + Layout.fillWidth: true + Layout.maximumHeight: 30 + + Label { + Layout.fillHeight: true + + Layout.maximumWidth: 42 + Layout.preferredWidth: 42 + Layout.minimumWidth: 42 + + text: qsTr("Quality") + font.pointSize: 10 + font.kerning: true + + horizontalAlignment: Text.AlignLeft + verticalAlignment: Text.AlignVCenter + } + + Item { + Layout.fillHeight: true + Layout.fillWidth: true + } + + ColumnLayout { + spacing: 0 + Layout.fillHeight: true + + Layout.maximumWidth: recordQualityValueLabel.width + Item { + Layout.fillHeight: true + Layout.fillWidth: true + } + + Label { + id: recordQualityValueLabel + + Layout.minimumWidth: 40 + + Layout.minimumHeight: 16 + Layout.preferredHeight: 16 + Layout.maximumHeight: 16 + + text: qsTr("VALUE ") + + font.pointSize: 10 + font.kerning: true + + horizontalAlignment: Text.AlignLeft + verticalAlignment: Text.AlignVCenter + } + + Item { + Layout.fillHeight: true + Layout.fillWidth: true + } + } + + Slider{ + id: recordQualitySlider + + Layout.fillHeight: true + + Layout.maximumWidth: 320 + Layout.preferredWidth: 320 + Layout.minimumWidth: 320 + + from: 0 + to: 500 + stepSize: 1 + + onMoved: { + slotRecordQualitySliderValueChanged(value) + } + } + } + + RowLayout { + spacing: 6 + + Layout.leftMargin: 20 + Layout.fillWidth: true + Layout.maximumHeight: 30 + + Label { + Layout.fillHeight: true + + Layout.maximumWidth: 42 + Layout.preferredWidth: 42 + Layout.minimumWidth: 42 + + text: qsTr("Save in") + font.pointSize: 10 + font.kerning: true + + horizontalAlignment: Text.AlignLeft + verticalAlignment: Text.AlignVCenter + } + + Item { + Layout.fillHeight: true + Layout.fillWidth: true + } + + HoverableRadiusButton { + id: recordPathButton + + Layout.maximumWidth: 320 + Layout.preferredWidth: 320 + Layout.minimumWidth: 320 + + Layout.minimumHeight: 30 + Layout.preferredHeight: 30 + Layout.maximumHeight: 30 + + radius: height / 2 + + icon.source: "qrc:/images/icons/round-folder-24px.svg" + icon.height: 24 + icon.width: 24 + + text: recordPath + fontPointSize: 10 + + onClicked: { + openRecordFolderSlot() + } + } + } + } + } + + Item { + Layout.fillWidth: true + Layout.minimumHeight: 20 + Layout.preferredHeight: 20 + Layout.maximumHeight: 20 + } + + // update setting panel + ColumnLayout { + spacing: 6 + Layout.fillWidth: true + visible: Qt.platform.os == "windows"? true : false + + Label { + Layout.fillWidth: true + Layout.minimumHeight: 21 + Layout.preferredHeight: 21 + Layout.maximumHeight: 21 + + text: qsTr("Updates") + font.pointSize: 13 + font.kerning: true + + horizontalAlignment: Text.AlignLeft + verticalAlignment: Text.AlignVCenter + } + + Item { + Layout.fillWidth: true + + Layout.minimumHeight: 10 + Layout.preferredHeight: 10 + Layout.maximumHeight: 10 + } + + ColumnLayout { + spacing: 6 + Layout.fillWidth: true + + ToggleSwitch { + id: autoUpdateCheckBox + + Layout.leftMargin: 20 + + labelText: "Check for updates automatically" + fontPointSize: 11 + + onSwitchToggled: { + slotSetUpdateAutomatic(checked) + } + } + + RowLayout { + spacing: 6 + + Layout.leftMargin: 20 + Layout.fillWidth: true + Layout.maximumHeight: 30 + + HoverableRadiusButton { + id: checkUpdateButton + + Layout.maximumWidth: 275 + Layout.preferredWidth: 275 + Layout.minimumWidth: 275 + + Layout.minimumHeight: 30 + Layout.preferredHeight: 30 + Layout.maximumHeight: 30 + + radius: height / 2 + + text: "Check for updates now" + fontPointSize: 10 + + onClicked: { + checkForUpdateSlot() + } + } + + Item { + Layout.fillHeight: true + Layout.fillWidth: true + } + } + + RowLayout { + spacing: 6 + + Layout.leftMargin: 20 + Layout.fillWidth: true + Layout.maximumHeight: 30 + + HoverableRadiusButton { + id: installBetaButton + + Layout.maximumWidth: 275 + Layout.preferredWidth: 275 + Layout.minimumWidth: 275 + + Layout.minimumHeight: 30 + Layout.preferredHeight: 30 + Layout.maximumHeight: 30 + + radius: height / 2 + + text: "Install the latest beta version" + fontPointSize: 10 + + onClicked: { + installBetaSlot() + } + } + + Item { + Layout.fillHeight: true + Layout.fillWidth: true + } + } + } + } + + // spacer on the bottom + Item { + Layout.fillHeight: true + Layout.fillWidth: true + } + } + + Item { + Layout.fillHeight: true + Layout.fillWidth: true + } + } + } +} diff --git a/src/settingsview/components/IconButton.qml b/src/settingsview/components/IconButton.qml new file mode 100644 index 00000000..7e992a9e --- /dev/null +++ b/src/settingsview/components/IconButton.qml @@ -0,0 +1,131 @@ +/* + * Copyright (C) 2019-2020 by Savoir-faire Linux + * Author: Yang Wang + * + * 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 . + */ + +import QtQuick 2.15 +import QtQuick.Window 2.14 +import QtQuick.Controls 2.14 +import QtQuick.Layouts 1.14 +import QtQuick.Controls.Universal 2.12 +import QtGraphicalEffects 1.14 + +import "../../constant" + +Button { + id: button + checkable: true + hoverEnabled: true + + property alias imageSource: buttonPix.source + property alias buttonText: buttonText.text + + property string backgroundColor: JamiTheme.releaseColor + property string onPressColor: JamiTheme.pressColor + property string onReleaseColor: JamiTheme.releaseColor + property string onEnterColor: JamiTheme.hoverColor + property string onExitColor: JamiTheme.transparentColor + property string checkedColor: JamiTheme.releaseColor + + signal checkedToggledForLeftPanel(var checked) + signal checkedToggledForRightPanel(var checked) + + function setCheckedState(check, triggerSignal) { + button.checked = check + if (triggerSignal) { + checkedToggledForLeftPanel(check) + checkedToggledForRightPanel(check) + } + button.background.color = check ? button.checkedColor : button.onExitColor + } + + onClicked: { + setCheckedState(true, true) + } + + Layout.minimumHeight: 60 + Layout.preferredHeight: 60 + Layout.maximumHeight: 60 + + Layout.fillWidth: true + + background: Rectangle { + anchors.fill: parent + color: parent.checked ? button.checkedColor : button.onExitColor + + RowLayout { + anchors.fill: parent + spacing: 24 + Image { + id: buttonPix + Layout.minimumHeight: 24 + Layout.preferredHeight: 24 + Layout.maximumHeight: 24 + + Layout.minimumWidth: 24 + Layout.preferredWidth: 24 + Layout.maximumWidth: 24 + + Layout.leftMargin: 24 + + Layout.alignment: Qt.AlignLeft | Qt.AlignVCenter + } + + Label { + id: buttonText + + Layout.alignment: Qt.AlignLeft | Qt.AlignVCenter + + Layout.fillHeight: true + Layout.fillWidth: true + + font.pointSize: 11 + font.kerning: true + + horizontalAlignment: Text.AlignLeft + verticalAlignment: Text.AlignVCenter + } + } + + MouseArea { + anchors.fill: parent + + hoverEnabled: true + + onPressed: { + if (!button.checked) { + parent.color = button.onPressColor + } + } + onReleased: { + button.clicked() + if (!button.checked) { + parent.color = button.onExitColor + } + } + onEntered: { + if (!button.checked) { + parent.color = button.onEnterColor + } + } + onExited: { + if (!button.checked) { + parent.color = button.onExitColor + } + } + } + } +} diff --git a/src/settingsview/components/LeftPanelView.qml b/src/settingsview/components/LeftPanelView.qml new file mode 100644 index 00000000..f11fe237 --- /dev/null +++ b/src/settingsview/components/LeftPanelView.qml @@ -0,0 +1,191 @@ +/* + * Copyright (C) 2019-2020 by Savoir-faire Linux + * Author: Yang Wang + * + * 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 . + */ + +import QtQuick 2.15 +import QtQuick.Window 2.14 +import QtQuick.Controls 1.4 as CT +import QtQuick.Controls 2.14 +import QtQuick.Controls.Universal 2.12 +import QtQuick.Layouts 1.3 +import QtGraphicalEffects 1.14 + +import "../../commoncomponents" + +ScrollView{ + id: leftPanelView + + property int contentViewportWidth: 200 + property int contentViewPortHeight: 768 + + property alias btnAccountSettings: accountSettingsButton + property alias btnGeneralSettings: generalSettingsButton + property alias btnMediaSettings: mediaSettingsButton + property alias btnPluginSettings: pluginSettingsButton + + signal btnExitClicked + + Component.onCompleted: { + accountSettingsButton.setCheckedState(true, true) + } + + anchors.fill: parent + clip: true + + ColumnLayout { + spacing: 0 + + width: contentViewportWidth + height: contentViewPortHeight + + Item { + Layout.fillWidth: true + Layout.maximumHeight: 13 + Layout.preferredHeight: 13 + Layout.minimumHeight: 13 + } + + RowLayout { + Layout.fillWidth: true + Layout.maximumHeight: 20 + Layout.preferredHeight: 20 + Layout.minimumHeight: 20 + + Layout.rightMargin: 14 + + Item { + Layout.fillHeight: true + + Layout.maximumWidth: 20 + Layout.preferredWidth: 20 + Layout.minimumWidth: 20 + } + + Label { + Layout.maximumWidth: 57 + Layout.preferredWidth: 57 + Layout.minimumWidth: 57 + + Layout.maximumHeight: 30 + Layout.preferredHeight: 30 + Layout.minimumHeight: 30 + + text: qsTr("Settings") + font.pointSize: 12 + font.kerning: true + + horizontalAlignment: Text.AlignLeft + verticalAlignment: Text.AlignVCenter + } + + Item { + Layout.fillWidth: true + Layout.fillHeight: true + } + + HoverableRadiusButton { + id: btnExitSettings + Layout.maximumWidth: 30 + Layout.preferredWidth: 30 + Layout.minimumWidth: 30 + + Layout.maximumHeight: 30 + Layout.preferredHeight: 30 + Layout.minimumHeight: 30 + + buttonImageHeight: height + buttonImageWidth: height + backgroundColor: "transparent" + + radius: height / 2 + + icon.source: "qrc:/images/icons/round-close-24px.svg" + icon.height: 24 + icon.width: 24 + + onClicked: { + btnExitClicked() + } + } + } + Item { + Layout.fillWidth: true + Layout.maximumHeight: 13 + Layout.preferredHeight: 13 + Layout.minimumHeight: 13 + } + + IconButton { + id: accountSettingsButton + + buttonText: qsTr("Account") + imageSource: "qrc:/images/icons/baseline-people-24px.svg" + + onCheckedToggledForLeftPanel: { + generalSettingsButton.setCheckedState(!checked, false) + mediaSettingsButton.setCheckedState(!checked, false) + pluginSettingsButton.setCheckedState(!checked, false) + } + } + + IconButton { + id: generalSettingsButton + + buttonText: qsTr("General") + imageSource: "qrc:/images/icons/round-settings-24px.svg" + + onCheckedToggledForLeftPanel: { + accountSettingsButton.setCheckedState(!checked, false) + mediaSettingsButton.setCheckedState(!checked, false) + pluginSettingsButton.setCheckedState(!checked, false) + } + } + + IconButton { + id: mediaSettingsButton + + buttonText: qsTr("Audio/Video") + imageSource: "qrc:/images/icons/baseline-desktop_windows-24px.svg" + + onCheckedToggledForLeftPanel: { + generalSettingsButton.setCheckedState(!checked, false) + accountSettingsButton.setCheckedState(!checked, false) + pluginSettingsButton.setCheckedState(!checked, false) + } + } + + IconButton { + id: pluginSettingsButton + + buttonText: qsTr("Plugins") + imageSource: "qrc:/images/icons/extension_24dp.svg" + + onCheckedToggledForLeftPanel: { + generalSettingsButton.setCheckedState(!checked, false) + accountSettingsButton.setCheckedState(!checked, false) + mediaSettingsButton.setCheckedState(!checked, false) + } + } + + Item { + Layout.fillWidth: true + Layout.fillHeight: true + } + } + +} + diff --git a/src/settingsview/components/LevelMeter.qml b/src/settingsview/components/LevelMeter.qml new file mode 100644 index 00000000..045d329a --- /dev/null +++ b/src/settingsview/components/LevelMeter.qml @@ -0,0 +1,47 @@ +/* + * Copyright (C) 2019-2020 by Savoir-faire Linux + * Author: Yang Wang + * + * 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 . + */ + +import QtQuick 2.15 +import QtQuick.Controls 2.15 + +ProgressBar { + id: levelMeter + + value: { + return clamp(rmsLevel * 300.0, 0.0, 100.0) + } + + property real rmsLevel: 0 + + function clamp(num,a,b){ + return Math.max(Math.min(num, Math.max(a, b)), Math.min(a, b)) + } + + function start(){ + rmsLevel = 0 + } + + function stop(){ + + } + + function setLevel(rmsLevelIn){ + rmsLevel = rmsLevelIn + } + +} diff --git a/src/settingsview/components/LinkDeviceDialog.qml b/src/settingsview/components/LinkDeviceDialog.qml new file mode 100644 index 00000000..c1caca16 --- /dev/null +++ b/src/settingsview/components/LinkDeviceDialog.qml @@ -0,0 +1,678 @@ +/* + * Copyright (C) 2020 by Savoir-faire Linux + * Author: Yang Wang + * + * 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 . + */ + +import QtQuick 2.15 +import QtQuick.Controls 2.14 +import QtQuick.Layouts 1.14 +import QtQuick.Controls.Styles 1.4 +import net.jami.Models 1.0 + +import "../../commoncomponents" + +Dialog { + id: linkDeviceDialog + + function openLinkDeviceDialog(){ + infoLabel.text = qsTr("This pin and the account password should be entered in your device within 10 minutes.") + passwordEdit.clear() + linkDeviceDialog.open() + if(ClientWrapper.accountAdaptor.hasPassword()){ + stackedWidget.currentIndex = 0 + } else { + setGeneratingPage() + } + } + + function setGeneratingPage(){ + if(passwordEdit.length === 0 && ClientWrapper.accountAdaptor.hasPassword()){ + setExportPage(NameDirectory.ExportOnRingStatus.WRONG_PASSWORD, "") + return + } + + stackedWidget.currentIndex = 1 + spinnerMovie.playing = true + + timerForExport.restart() + } + + function slotExportOnRing(){ + ClientWrapper.accountModel.exportOnRing(ClientWrapper.utilsAdaptor.getCurrAccId(),passwordEdit.text) + } + + Timer{ + id: timerForExport + + repeat: false + interval: 200 + + onTriggered: { + timeOut.restart() + slotExportOnRing() + } + } + + Timer{ + id: timeOut + + repeat: false + interval: exportTimeout + + onTriggered: { + setExportPage(NameDirectory.ExportOnRingStatus.NETWORK_ERROR, "") + } + } + + function setExportPage(status, pin){ + timeOut.stop() + + if(status === NameDirectory.ExportOnRingStatus.SUCCESS){ + infoLabel.isSucessState = true + yourPinLabel.visible = true + exportedPIN.visible = true + infoLabel.text = qsTr("This pin and the account password should be entered in your device within 10 minutes.") + exportedPIN.text = pin + } else { + infoLabel.isSucessState = false + yourPinLabel.visible = false + exportedPIN.visible = false + + switch(status){ + case NameDirectory.ExportOnRingStatus.WRONG_PASSWORD: + infoLabel.text = qsTr("Incorrect password") + + break + case NameDirectory.ExportOnRingStatus.NETWORK_ERROR: + infoLabel.text = qsTr("Error connecting to the network.\nPlease try again later.") + + break + case NameDirectory.ExportOnRingStatus.INVALID: + infoLabel.text = qsTr("Something went wrong.\n") + + break + } + } + stackedWidget.currentIndex = 2 + } + + property int exportTimeout : 20000 + + Connections{ + target: ClientWrapper.nameDirectory + + function onExportOnRingEnded(status, pin){ + setExportPage(status, pin) + } + } + + visible: false + + anchors.centerIn: parent.Center + x: (parent.width - width) / 2 + y: (parent.height - height) / 2 + + title: qsTr("Link another device") + + onClosed: { + if(infoLabel.isSucessState){ + accept() + } else { + reject() + } + } + + contentItem: Rectangle{ + implicitWidth: 365 + implicitHeight: 208 + + StackLayout{ + id: stackedWidget + anchors.fill: parent + + currentIndex: 2 + + Rectangle{ + id: passwordConfirmPage + + Layout.fillWidth: true + Layout.fillHeight: true + + Layout.leftMargin: 11 + Layout.rightMargin: 11 + Layout.topMargin: 11 + Layout.bottomMargin: 11 + + ColumnLayout{ + anchors.fill: parent + spacing: 7 + + Layout.alignment: Qt.AlignHCenter | Qt.AlignVCenter + + Item{ + Layout.alignment: Qt.AlignHCenter + + Layout.fillHeight: true + Layout.maximumHeight: 20 + Layout.preferredHeight: 20 + Layout.minimumHeight: 20 + } + + Label{ + Layout.preferredWidth: 219 + Layout.alignment: Qt.AlignHCenter + wrapMode: Text.Wrap + text: qsTr("Enter your account password") + font.pointSize: 8 + font.kerning: true + horizontalAlignment: Text.AlignHCenter + verticalAlignment: Text.AlignVCenter + } + + Item{ + Layout.alignment: Qt.AlignHCenter + + Layout.fillHeight: true + + Layout.maximumHeight: 20 + Layout.preferredHeight: 20 + Layout.minimumHeight: 20 + } + + InfoLineEdit{ + id: passwordEdit + + Layout.alignment: Qt.AlignHCenter + + Layout.minimumWidth: 294 + Layout.preferredWidth: 294 + + Layout.preferredHeight: 30 + Layout.minimumHeight: 30 + + echoMode: TextInput.Password + + placeholderText: qsTr("Password") + } + + Item{ + Layout.alignment: Qt.AlignHCenter + + Layout.fillHeight: true + + Layout.maximumHeight: 20 + Layout.preferredHeight: 20 + Layout.minimumHeight: 20 + } + + RowLayout{ + spacing: 7 + + Layout.alignment: Qt.AlignHCenter + Layout.fillWidth: true + + Item{ + Layout.fillWidth: true + + Layout.maximumHeight: 20 + Layout.preferredHeight: 20 + Layout.minimumHeight: 20 + } + + HoverableRadiusButton{ + id: btnPasswordOk + + Layout.maximumWidth: 130 + Layout.preferredWidth: 130 + Layout.minimumWidth: 130 + + Layout.maximumHeight: 30 + Layout.preferredHeight: 30 + Layout.minimumHeight: 30 + + radius: height /2 + + text: qsTr("Register") + font.pointSize: 10 + font.kerning: true + + onClicked: { + setGeneratingPage() + } + } + + Item{ + Layout.fillWidth: true + Layout.minimumWidth: 40 + + Layout.maximumHeight: 20 + Layout.preferredHeight: 20 + Layout.minimumHeight: 20 + } + + HoverableButtonTextItem { + id: btnCancel + + Layout.maximumWidth: 130 + Layout.preferredWidth: 130 + Layout.minimumWidth: 130 + + Layout.maximumHeight: 30 + Layout.preferredHeight: 30 + Layout.minimumHeight: 30 + + backgroundColor: "red" + onEnterColor: Qt.rgba(150 / 256, 0, 0, 0.7) + onDisabledBackgroundColor: Qt.rgba( + 255 / 256, + 0, 0, 0.8) + onPressColor: backgroundColor + textColor: "white" + + radius: height /2 + + text: qsTr("Cancel") + font.pointSize: 10 + font.kerning: true + + onClicked: { + reject() + } + } + + Item{ + Layout.fillWidth: true + Layout.minimumWidth: 40 + + Layout.maximumHeight: 20 + Layout.preferredHeight: 20 + Layout.minimumHeight: 20 + } + } + + Item{ + Layout.alignment: Qt.AlignHCenter + + Layout.fillHeight: true + + Layout.maximumHeight: 20 + Layout.preferredHeight: 20 + Layout.minimumHeight: 20 + } + } + } + + Rectangle{ + id: exportingPage + + Layout.fillWidth: true + Layout.fillHeight: true + + Layout.leftMargin: 11 + Layout.rightMargin: 11 + Layout.topMargin: 11 + Layout.bottomMargin: 11 + + ColumnLayout{ + anchors.fill: parent + spacing: 7 + + Layout.alignment: Qt.AlignHCenter | Qt.AlignVCenter + + Item{ + Layout.alignment: Qt.AlignHCenter + + Layout.fillHeight: true + Layout.minimumHeight: 40 + + Layout.maximumWidth: 20 + Layout.preferredWidth: 20 + Layout.minimumWidth: 20 + } + + RowLayout{ + Layout.fillWidth: true + spacing: 0 + + Layout.maximumHeight: 30 + + Item{ + Layout.fillWidth: true + + Layout.maximumHeight: 20 + Layout.preferredHeight: 20 + Layout.minimumHeight: 20 + } + + Label{ + Layout.alignment: Qt.AlignHCenter + + Layout.maximumWidth: 0 + Layout.preferredWidth: 341 + + Layout.minimumHeight: 0 + Layout.preferredHeight: 30 + Layout.maximumHeight: 30 + + wrapMode: Text.Wrap + text: qsTr("Exporting Account") + font.pointSize: 8 + font.kerning: true + horizontalAlignment: Text.AlignHCenter + verticalAlignment: Text.AlignVCenter + } + + Item{ + Layout.fillWidth: true + + Layout.maximumHeight: 20 + Layout.preferredHeight: 20 + Layout.minimumHeight: 20 + } + } + + Item{ + Layout.alignment: Qt.AlignHCenter + + Layout.fillHeight: true + + Layout.maximumWidth: 20 + Layout.preferredWidth: 20 + Layout.minimumWidth: 20 + } + + RowLayout{ + spacing: 7 + + Item{ + Layout.fillWidth: true + + Layout.maximumHeight: 20 + Layout.preferredHeight: 20 + Layout.minimumHeight: 20 + } + + Label{ + id: exportingSpinner + + Layout.alignment: Qt.AlignHCenter + + Layout.maximumWidth: 96 + Layout.preferredWidth: 96 + Layout.minimumWidth: 96 + + Layout.maximumHeight: 96 + Layout.preferredHeight: 96 + Layout.minimumHeight: 96 + + background: Rectangle { + anchors.fill: parent + AnimatedImage { + id: spinnerMovie + + anchors.fill: parent + + source: "qrc:/images/jami_eclipse_spinner.gif" + + playing: exportingSpinner.visible + paused: false + fillMode: Image.PreserveAspectFit + mipmap: true + } + } + } + + Item{ + Layout.fillWidth: true + + Layout.maximumHeight: 20 + Layout.preferredHeight: 20 + Layout.minimumHeight: 20 + } + + } + + Item{ + Layout.alignment: Qt.AlignHCenter + + Layout.fillHeight: true + Layout.minimumHeight: 40 + + Layout.maximumWidth: 20 + Layout.preferredWidth: 20 + Layout.minimumWidth: 20 + } + } + } + + Rectangle{ + id: exportedPage + + Layout.fillWidth: true + Layout.fillHeight: true + + Layout.leftMargin: 11 + Layout.rightMargin: 11 + Layout.topMargin: 11 + Layout.bottomMargin: 11 + + ColumnLayout{ + anchors.fill: parent + spacing: 7 + + Layout.alignment: Qt.AlignHCenter | Qt.AlignVCenter + + Item{ + Layout.fillHeight: true + + Layout.maximumWidth: 20 + Layout.preferredWidth: 20 + Layout.minimumWidth: 20 + } + + RowLayout{ + spacing: 7 + + Layout.alignment: Qt.AlignHCenter + Layout.fillWidth: true + + Item{ + Layout.fillWidth: true + + Layout.maximumHeight: 20 + Layout.preferredHeight: 20 + Layout.minimumHeight: 20 + } + + Label{ + id: yourPinLabel + + Layout.alignment: Qt.AlignHCenter + + Layout.preferredHeight: 25 + + wrapMode: Text.Wrap + text: "Your PIN is:" + font.pointSize: 8 + font.kerning: true + horizontalAlignment: Text.AlignHCenter + verticalAlignment: Text.AlignVCenter + } + + Item{ + Layout.alignment: Qt.AlignHCenter + + Layout.maximumWidth: 20 + Layout.preferredWidth: 20 + Layout.minimumWidth: 20 + + Layout.maximumHeight: 20 + Layout.preferredHeight: 20 + Layout.minimumHeight: 20 + } + + Label{ + id: exportedPIN + + Layout.alignment: Qt.AlignHCenter + + Layout.preferredHeight: 25 + + wrapMode: Text.Wrap + text: "PIN" + font.pointSize: 12 + font.kerning: true + horizontalAlignment: Text.AlignHCenter + verticalAlignment: Text.AlignVCenter + } + + Item{ + Layout.fillWidth: true + + Layout.maximumHeight: 20 + Layout.preferredHeight: 20 + Layout.minimumHeight: 20 + } + } + + RowLayout{ + spacing: 7 + + Layout.alignment: Qt.AlignHCenter + Layout.fillWidth: true + + Item{ + Layout.fillWidth: true + + Layout.maximumHeight: 20 + Layout.preferredHeight: 20 + Layout.minimumHeight: 20 + } + + Label{ + id: infoLabel + + property bool isSucessState: false + property int borderWidth : isSucessState? 1 : 0 + property int borderRadius : isSucessState? 15 : 0 + property string backgroundColor : isSucessState? "whitesmoke" : "transparent" + property string borderColor : isSucessState? "lightgray" : "transparent" + color: isSucessState ? "#2b5084" : "black" + padding: isSucessState ? 8 : 0 + + Layout.alignment: Qt.AlignHCenter + Layout.preferredWidth: 320 + Layout.preferredHeight: 50 + + wrapMode: Text.Wrap + text: qsTr("This pin and the account password should be entered in your device within 10 minutes.") + font.pointSize: 8 + font.kerning: true + + horizontalAlignment: Text.AlignHCenter + verticalAlignment: Text.AlignVCenter + + background: Rectangle{ + id: infoLabelBackground + + anchors.fill: parent + border.width: infoLabel.borderWidth + border.color: infoLabel.borderColor + radius: infoLabel.borderRadius + color: infoLabel.backgroundColor + } + } + + Item{ + Layout.fillWidth: true + + Layout.maximumHeight: 20 + Layout.preferredHeight: 20 + Layout.minimumHeight: 20 + } + } + + Item{ + Layout.fillHeight: true + + Layout.maximumWidth: 20 + Layout.preferredWidth: 20 + Layout.minimumWidth: 20 + } + + RowLayout{ + spacing: 7 + + Layout.alignment: Qt.AlignHCenter + Layout.fillWidth: true + + Item{ + Layout.fillWidth: true + + Layout.maximumHeight: 20 + Layout.preferredHeight: 20 + Layout.minimumHeight: 20 + } + + HoverableRadiusButton{ + id: btnCloseExportDialog + + Layout.alignment: Qt.AlignHCenter + + Layout.maximumWidth: 130 + Layout.preferredWidth: 130 + Layout.minimumWidth: 130 + + Layout.maximumHeight: 30 + Layout.preferredHeight: 30 + Layout.minimumHeight: 30 + + radius: height /2 + + text: qsTr("Close") + font.pointSize: 10 + font.kerning: true + + onClicked: { + if(infoLabel.isSucessState){ + accept() + } else { + reject() + } + } + } + + Item{ + Layout.fillWidth: true + + Layout.maximumHeight: 20 + Layout.preferredHeight: 20 + Layout.minimumHeight: 20 + } + } + + Item{ + Layout.fillHeight: true + + Layout.maximumWidth: 20 + Layout.preferredWidth: 20 + Layout.minimumWidth: 20 + } + } + } + } + } +} diff --git a/src/settingsview/components/NameRegistrationDialog.qml b/src/settingsview/components/NameRegistrationDialog.qml new file mode 100644 index 00000000..ab9988d3 --- /dev/null +++ b/src/settingsview/components/NameRegistrationDialog.qml @@ -0,0 +1,555 @@ +/* + * Copyright (C) 2020 by Savoir-faire Linux + * Author: Yang Wang + * + * 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 . + */ + +import QtQuick 2.15 +import QtQuick.Controls 2.14 +import QtQuick.Layouts 1.14 +import QtQuick.Controls.Styles 1.4 +import net.jami.Models 1.0 + +import "../../commoncomponents" + +Dialog { + id: nameRegistrationDialog + + property string registerdName : "" + + function openNameRegistrationDialog(registerNameIn){ + registerdName = registerNameIn + lblRegistrationError.text = qsTr("Something went wrong") + passwordEdit.clear() + if(ClientWrapper.accountAdaptor.hasPassword()){ + stackedWidget.currentIndex = 0 + } else { + startRegistration() + } + + nameRegistrationDialog.open() + } + + function startRegistration(){ + startSpinner() + timerForStartRegistration.restart() + } + + function slotStartNameRegistration(){ + var password = passwordEdit.text + ClientWrapper.accountModel.registerName(ClientWrapper.utilsAdaptor.getCurrAccId(), password, registerdName) + } + + function startSpinner(){ + stackedWidget.currentIndex = 1 + spinnerLabel.visible = true + spinnerMovie.playing = true + } + + Timer{ + id: timerForStartRegistration + + interval: 100 + repeat: false + + onTriggered: { + slotStartNameRegistration() + } + } + + Connections{ + target: ClientWrapper.nameDirectory + + function onNameRegistrationEnded(status, name){ + if(status === NameDirectory.RegisterNameStatus.SUCCESS){ + accept() + } else { + switch(status){ + case NameDirectory.RegisterNameStatus.WRONG_PASSWORD: + lblRegistrationError.text = qsTr("Incorrect password") + break + + case NameDirectory.RegisterNameStatus.NETWORK_ERROR: + lblRegistrationError.text = qsTr("Network error") + break + default: + break + } + stackedWidget.currentIndex = 2 + } + } + } + + visible: false + + anchors.centerIn: parent.Center + x: (parent.width - width) / 2 + y: (parent.height - height) / 2 + + title: qsTr("Set Registered Name") + + onClosed: { + reject() + } + + contentItem: Rectangle{ + implicitWidth: 365 + implicitHeight: 208 + + StackLayout{ + id: stackedWidget + anchors.fill: parent + + currentIndex: 0 + + Rectangle{ + id: passwordConfirmPage + + Layout.fillWidth: true + Layout.fillHeight: true + + Layout.leftMargin: 11 + Layout.rightMargin: 11 + Layout.topMargin: 11 + Layout.bottomMargin: 11 + + ColumnLayout{ + anchors.fill: parent + spacing: 7 + + Layout.alignment: Qt.AlignHCenter | Qt.AlignVCenter + + Item{ + Layout.alignment: Qt.AlignHCenter + + Layout.fillHeight: true + Layout.maximumHeight: 20 + Layout.preferredHeight: 20 + Layout.minimumHeight: 20 + } + + Label{ + Layout.preferredWidth: 219 + Layout.alignment: Qt.AlignHCenter + wrapMode: Text.Wrap + text: qsTr("Enter your account password") + font.pointSize: 8 + font.kerning: true + horizontalAlignment: Text.AlignHCenter + verticalAlignment: Text.AlignVCenter + } + + Item{ + Layout.alignment: Qt.AlignHCenter + + Layout.fillHeight: true + + Layout.maximumHeight: 20 + Layout.preferredHeight: 20 + Layout.minimumHeight: 20 + } + + InfoLineEdit{ + id: passwordEdit + + Layout.alignment: Qt.AlignHCenter + + Layout.minimumWidth: 294 + Layout.preferredWidth: 294 + + Layout.preferredHeight: 30 + Layout.minimumHeight: 30 + + echoMode: TextInput.Password + + placeholderText: qsTr("Password") + } + + Item{ + Layout.alignment: Qt.AlignHCenter + + Layout.fillHeight: true + + Layout.maximumHeight: 20 + Layout.preferredHeight: 20 + Layout.minimumHeight: 20 + } + + RowLayout{ + spacing: 7 + + Layout.alignment: Qt.AlignHCenter + + Layout.fillWidth: true + + Item{ + Layout.fillWidth: true + + Layout.maximumHeight: 20 + Layout.preferredHeight: 20 + Layout.minimumHeight: 20 + } + + HoverableRadiusButton{ + id: btnRegister + + Layout.maximumWidth: 130 + Layout.preferredWidth: 130 + Layout.minimumWidth: 130 + + Layout.maximumHeight: 30 + Layout.preferredHeight: 30 + Layout.minimumHeight: 30 + + radius: height /2 + + text: qsTr("Register") + font.pointSize: 10 + font.kerning: true + + onClicked: { + startRegistration() + } + } + + Item{ + Layout.fillWidth: true + Layout.minimumWidth: 40 + + Layout.maximumHeight: 20 + Layout.preferredHeight: 20 + Layout.minimumHeight: 20 + } + + HoverableButtonTextItem { + id: btnCancel + + Layout.maximumWidth: 130 + Layout.preferredWidth: 130 + Layout.minimumWidth: 130 + + Layout.maximumHeight: 30 + Layout.preferredHeight: 30 + Layout.minimumHeight: 30 + + backgroundColor: "red" + onEnterColor: Qt.rgba(150 / 256, 0, 0, 0.7) + onDisabledBackgroundColor: Qt.rgba( + 255 / 256, + 0, 0, 0.8) + onPressColor: backgroundColor + textColor: "white" + + radius: height /2 + + text: qsTr("Cancel") + font.pointSize: 10 + font.kerning: true + + onClicked: { + reject() + } + } + + Item{ + Layout.fillWidth: true + Layout.minimumWidth: 40 + + Layout.maximumHeight: 20 + Layout.preferredHeight: 20 + Layout.minimumHeight: 20 + } + } + + Item{ + Layout.alignment: Qt.AlignHCenter + + Layout.fillHeight: true + + Layout.maximumHeight: 20 + Layout.preferredHeight: 20 + Layout.minimumHeight: 20 + } + } + } + + Rectangle{ + id: registeringPage + + Layout.fillWidth: true + Layout.fillHeight: true + + Layout.leftMargin: 11 + Layout.rightMargin: 11 + Layout.topMargin: 11 + Layout.bottomMargin: 11 + + ColumnLayout{ + anchors.fill: parent + spacing: 7 + + Layout.alignment: Qt.AlignHCenter | Qt.AlignVCenter + + Item{ + Layout.alignment: Qt.AlignHCenter + + Layout.fillHeight: true + Layout.minimumHeight: 40 + + Layout.maximumWidth: 20 + Layout.preferredWidth: 20 + Layout.minimumWidth: 20 + } + + RowLayout{ + Layout.fillWidth: true + spacing: 0 + + Layout.maximumHeight: 30 + + Item{ + Layout.fillWidth: true + + Layout.maximumHeight: 20 + Layout.preferredHeight: 20 + Layout.minimumHeight: 20 + } + + Label{ + Layout.alignment: Qt.AlignHCenter + + Layout.maximumWidth: 0 + Layout.preferredWidth: 341 + + Layout.minimumHeight: 0 + Layout.preferredHeight: 30 + Layout.maximumHeight: 30 + + wrapMode: Text.Wrap + text: qsTr("Registering Name") + font.pointSize: 8 + font.kerning: true + horizontalAlignment: Text.AlignHCenter + verticalAlignment: Text.AlignVCenter + } + + Item{ + Layout.fillWidth: true + + Layout.maximumHeight: 20 + Layout.preferredHeight: 20 + Layout.minimumHeight: 20 + } + } + + Item{ + Layout.alignment: Qt.AlignHCenter + + Layout.fillHeight: true + + Layout.maximumWidth: 20 + Layout.preferredWidth: 20 + Layout.minimumWidth: 20 + } + + RowLayout{ + spacing: 7 + + Item{ + Layout.fillWidth: true + + Layout.maximumHeight: 20 + Layout.preferredHeight: 20 + Layout.minimumHeight: 20 + } + + Label{ + id: spinnerLabel + + Layout.alignment: Qt.AlignHCenter + + Layout.maximumWidth: 96 + Layout.preferredWidth: 96 + Layout.minimumWidth: 96 + + Layout.maximumHeight: 96 + Layout.preferredHeight: 96 + Layout.minimumHeight: 96 + + background: Rectangle { + anchors.fill: parent + AnimatedImage { + id: spinnerMovie + + anchors.fill: parent + + source: "qrc:/images/jami_eclipse_spinner.gif" + + playing: spinnerLabel.visible + paused: false + fillMode: Image.PreserveAspectFit + mipmap: true + } + } + } + + Item{ + Layout.fillWidth: true + + Layout.maximumHeight: 20 + Layout.preferredHeight: 20 + Layout.minimumHeight: 20 + } + + } + + Item{ + Layout.alignment: Qt.AlignHCenter + + Layout.fillHeight: true + Layout.minimumHeight: 40 + + Layout.maximumWidth: 20 + Layout.preferredWidth: 20 + Layout.minimumWidth: 20 + } + } + } + + Rectangle{ + id: nameNotRegisteredPage + + Layout.fillWidth: true + Layout.fillHeight: true + + ColumnLayout{ + anchors.fill: parent + + Item{ + Layout.fillHeight: true + Layout.minimumHeight: 40 + + Layout.maximumWidth: 20 + Layout.preferredWidth: 20 + Layout.minimumWidth: 20 + } + + RowLayout{ + spacing: 7 + Layout.fillWidth: true + + Item{ + Layout.fillWidth: true + + Layout.maximumHeight: 20 + Layout.preferredHeight: 20 + Layout.minimumHeight: 20 + } + + Label{ + id: lblRegistrationError + + Layout.alignment: Qt.AlignHCenter + + Layout.maximumWidth: 0 + Layout.preferredWidth: 341 + + Layout.minimumHeight: 0 + Layout.preferredHeight: 30 + Layout.maximumHeight: 30 + + wrapMode: Text.Wrap + text: qsTr("Something went wrong") + font.pointSize: 8 + font.kerning: true + color: "red" + horizontalAlignment: Text.AlignHCenter + verticalAlignment: Text.AlignVCenter + } + + Item{ + Layout.fillWidth: true + + Layout.maximumHeight: 20 + Layout.preferredHeight: 20 + Layout.minimumHeight: 20 + } + } + + Item{ + Layout.fillHeight: true + Layout.minimumHeight: 40 + + Layout.maximumWidth: 20 + Layout.preferredWidth: 20 + Layout.minimumWidth: 20 + } + + RowLayout{ + spacing: 7 + Layout.fillWidth: true + + Item{ + Layout.fillWidth: true + + Layout.maximumHeight: 20 + Layout.preferredHeight: 20 + Layout.minimumHeight: 20 + } + + HoverableRadiusButton{ + id: btnCloseRegisterDialog + + Layout.maximumWidth: 130 + Layout.preferredWidth: 130 + Layout.minimumWidth: 130 + + Layout.maximumHeight: 30 + Layout.preferredHeight: 30 + Layout.minimumHeight: 30 + + radius: height /2 + + text: qsTr("Close") + font.pointSize: 10 + font.kerning: true + + onClicked: { + reject() + } + } + + Item{ + Layout.fillWidth: true + + Layout.maximumHeight: 20 + Layout.preferredHeight: 20 + Layout.minimumHeight: 20 + } + } + + Item{ + Layout.fillHeight: true + Layout.minimumHeight: 40 + + Layout.maximumWidth: 20 + Layout.preferredWidth: 20 + Layout.minimumWidth: 20 + } + } + } + } + } +} diff --git a/src/settingsview/components/PluginItemDelegate.qml b/src/settingsview/components/PluginItemDelegate.qml new file mode 100644 index 00000000..3946a150 --- /dev/null +++ b/src/settingsview/components/PluginItemDelegate.qml @@ -0,0 +1,176 @@ +/* + * Copyright (C) 2019-2020 by Savoir-faire Linux + * Author: Yang Wang + * + * 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 . + */ + +import QtQuick 2.15 +import QtQuick.Window 2.15 +import QtQuick.Controls 2.15 +import QtQuick.Controls.Universal 2.12 +import QtQuick.Layouts 1.3 +import QtGraphicalEffects 1.14 +import QtQuick.Controls.Styles 1.4 +import net.jami.Models 1.0 + +import "../../commoncomponents" + +ItemDelegate { + id: pluginItemDelegate + + property string pluginName : "" + property string pluginId: "" + property string pluginIcon: "" + property bool isLoaded: false + + signal btnLoadPluginToggled + signal btnPreferencesPluginClicked + + highlighted: ListView.isCurrentItem + + RowLayout{ + anchors.fill: parent + + Label{ + Layout.leftMargin: 7 + Layout.bottomMargin: 7 + + Layout.minimumWidth: 30 + Layout.preferredWidth: 30 + Layout.maximumWidth: 30 + + Layout.minimumHeight: 30 + Layout.preferredHeight: 30 + Layout.maximumHeight: 30 + + background: Rectangle{ + anchors.fill: parent + Image { + anchors.fill: parent + source: "file:"+pluginIcon + } + } + } + + ColumnLayout{ + Layout.fillWidth: true + Layout.fillHeight: true + + Layout.leftMargin: 7 + Layout.topMargin: 7 + Layout.bottomMargin: 7 + + RowLayout{ + + Layout.minimumHeight: 30 + + Label{ + id: labelDeviceId + + Layout.minimumHeight: 20 + + font.pointSize: 10 + font.kerning: true + text: pluginName === "" ? pluginId : pluginName + } + + Item{ + Layout.fillWidth: true + + Layout.minimumWidth: 0 + Layout.minimumHeight: 20 + } + } + } + + Switch { + id: loadSwitch + property bool isHovering: false + + Layout.bottomMargin: 7 + Layout.rightMargin: 15 + + Layout.maximumWidth: 30 + Layout.preferredWidth: 30 + Layout.minimumWidth: 30 + + Layout.minimumHeight: 30 + Layout.preferredHeight: 30 + Layout.maximumHeight: 30 + + ToolTip.visible: isHovering + ToolTip.text: { + return qsTr("Load/Unload") + } + + checked: isLoaded + onClicked: { + btnLoadPluginToggled() + } + + background: Rectangle { + id: switchBackground + MouseArea { + id: btnMouseArea + anchors.fill: parent + hoverEnabled: true + onPressed: { + } + onReleased: { + loadSwitch.clicked() + } + onEntered: { + loadSwitch.isHovering = true + } + onExited: { + loadSwitch.isHovering = false + } + } + } + } + + HoverableRadiusButton{ + id: btnPreferencesPlugin + + Layout.bottomMargin: 7 + Layout.rightMargin: 7 + Layout.alignment: Qt.AlignRight + + Layout.minimumWidth: 30 + Layout.preferredWidth: 30 + Layout.maximumWidth: 30 + + Layout.minimumHeight: 30 + Layout.preferredHeight: 30 + Layout.maximumHeight: 30 + + buttonImageHeight: height + buttonImageWidth: height + + source:{ + return "qrc:/images/icons/round-settings-24px.svg" + } + + ToolTip.visible: isHovering + ToolTip.text: { + return qsTr("Edit preferences") + } + + onClicked: { + btnPreferencesPluginClicked() + } + } + } +} diff --git a/src/settingsview/components/PluginListPreferencesView.qml b/src/settingsview/components/PluginListPreferencesView.qml new file mode 100644 index 00000000..9b8c03af --- /dev/null +++ b/src/settingsview/components/PluginListPreferencesView.qml @@ -0,0 +1,334 @@ +/* + * Copyright (C) 2019-2020 by Savoir-faire Linux + * Author: Yang Wang + * + * 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 . + */ + +import QtQuick 2.15 +import QtQuick.Window 2.14 +import QtQuick.Controls 2.14 +import QtQuick.Controls.Universal 2.12 +import QtQuick.Layouts 1.3 +import Qt.labs.platform 1.1 +import QtGraphicalEffects 1.14 +import net.jami.Models 1.0 +import "../../commoncomponents" + +Rectangle { + id: pluginListPreferencesViewRect + + enum Type { + LIST, + DEFAULT + } + + signal updatePluginList + + property string pluginName: "" + property string pluginIcon: "" + property string pluginId: "" + property bool isLoaded: false + property int size: 0 + + visible: false + + function updatePreferenceListDisplayed(show){ + // settings + getSize(pluginId, show) + preferenceItemListModel.pluginId = pluginId + preferenceItemListModel.reset() + } + + function resetPluginSlot(){ + resetPluginMessageBox.open() + } + + function resetPlugin(){ + ClientWrapper.pluginModel.resetPluginPreferencesValues(pluginId, isLoaded) + updatePluginList() + } + + function uninstallPluginSlot(){ + uninstallPluginMessageBox.open() + } + + function uninstallPlugin(){ + ClientWrapper.pluginModel.uninstallPlugin(pluginId) + updatePluginList() + } + + function getSize(pluginId, show){ + size = 50 * ClientWrapper.pluginModel.getPluginPreferences(pluginId).length + if (show) { + height = 200 + size + pluginPreferenceView.height = size + } else { + height = 25 + } + } + + function editPreferenceSlot(preferenceType, preferenceName, preferenceEntryValues){ + switch (preferenceType){ + case PluginListPreferencesView.LIST: + console.log("LIST") + editListMessageBox.preferenceName = preferenceName + editListMessageBox.preferenceEntryValues = preferenceEntryValues + editListMessageBox.open() + break + case PluginListPreferencesView.DEFAULT: + console.log("Unrecognizable Type") + break + default: + console.log("Unrecognizable Type") + break + } + } + + function setPreference(pluginId, preferenceKey, preferenceNewValue) + { + ClientWrapper.pluginModel.setPluginPreferences(pluginId, preferenceKey, preferenceNewValue, isLoaded) + preferenceItemListModel.reset() + } + + MessageBox{ + id: uninstallPluginMessageBox + + title:qsTr("Uninstall plugin") + text :qsTr("Are you sure you wish to uninstall " + pluginName + " ?") + standardButtons: StandardButton.Ok | StandardButton.Cancel + + onYes: { + accepted() + } + + onNo:{ + rejected() + } + + onDiscard: { + rejected() + } + + onAccepted: { + uninstallPlugin() + pluginListPreferencesViewRect.visible = false + } + + onRejected: {} + } + + MessageBox{ + id: resetPluginMessageBox + + title:qsTr("Reset preferences") + text :qsTr("Are you sure you wish to reset "+ pluginName + " preferences?") + + standardButtons: StandardButton.Ok | StandardButton.Cancel + + onYes: { + accepted() + } + + onNo:{ + rejected() + } + + onDiscard: { + rejected() + } + + onAccepted: { + resetPlugin() + } + + onRejected: {} + } + + MessageBox{ + id: editListMessageBox + + property string preferenceName: "" + property var preferenceEntryValues: [] + + title:qsTr("Edit " + preferenceName) + text :qsTr(preferenceName + " options: " + preferenceEntryValues) + + standardButtons: StandardButton.Ok | StandardButton.Cancel + + onYes: { + accepted() + } + + onNo:{ + rejected() + } + + onDiscard: { + rejected() + } + + onAccepted: { + // setPreference(pluginId, preferenceItemDelegate.preferenceKey, preferenceItemDelegate.preferenceNewValue) + } + + onRejected: {} + } + + PreferenceItemListModel { + id: preferenceItemListModel + } + + Layout.fillHeight: true + Layout.fillWidth: true + + ColumnLayout { + spacing: 6 + Layout.fillHeight: true + Layout.maximumWidth: 580 + Layout.preferredWidth: 580 + Layout.minimumWidth: 580 + + Label{ + Layout.alignment: Qt.AlignHCenter + + Layout.minimumWidth: 30 + Layout.preferredWidth: 30 + Layout.maximumWidth: 30 + Layout.minimumHeight: 30 + Layout.preferredHeight: 30 + Layout.maximumHeight: 30 + + background: Rectangle{ + anchors.fill: parent + Image { + anchors.fill: parent + source: "file:"+pluginIcon + } + } + } + + Label { + Layout.alignment: Qt.AlignHCenter + Layout.topMargin: 10 + Layout.fillWidth: true + Layout.minimumHeight: 25 + Layout.preferredHeight: 25 + Layout.maximumHeight: 25 + + text: qsTr(pluginName + "\npreferences") + font.pointSize: 13 + font.kerning: true + + horizontalAlignment: Text.AlignHCenter + verticalAlignment: Text.AlignVCenter + } + + RowLayout { + spacing: 6 + Layout.fillWidth: true + Layout.topMargin: 10 + Layout.maximumHeight: 30 + Layout.preferredHeight: 30 + Layout.minimumHeight: 30 + + HoverableRadiusButton { + id: resetButton + + Layout.maximumWidth: 157 + Layout.preferredWidth: 157 + Layout.minimumWidth: 157 + + Layout.fillHeight: true + + radius: height / 2 + + icon.source: "qrc:/images/icons/settings_backup_restore-black-18dp.svg" + icon.height: 24 + icon.width: 24 + + text: qsTr("Reset") + fontPointSize: 10 + font.kerning: true + + onClicked: { + resetPluginSlot() + } + } + + HoverableRadiusButton { + id: uninstallButton + + Layout.maximumWidth: 157 + Layout.preferredWidth: 157 + Layout.minimumWidth: 157 + + Layout.fillHeight: true + + radius: height / 2 + + icon.source: "qrc:/images/icons/ic_delete_black_18dp_2x.png" + icon.height: 24 + icon.width: 24 + + text: qsTr("Uninstall") + fontPointSize: 10 + font.kerning: true + + onClicked: { + uninstallPluginSlot() + } + } + } + + ListViewJami { + id: pluginPreferenceView + + Layout.minimumWidth: 320 + Layout.preferredWidth: 320 + Layout.maximumWidth: 320 + + Layout.minimumHeight: 0 + Layout.preferredHeight: height + Layout.maximumHeight: 1000 + + model: preferenceItemListModel + + delegate: PreferenceItemDelegate{ + id: preferenceItemDelegate + + width: pluginPreferenceView.width + height: 50 + + preferenceKey : PreferenceKey + preferenceName: PreferenceName + preferenceSummary: PreferenceSummary + preferenceType: PreferenceType + preferenceDefaultValue: PreferenceDefaultValue + preferenceEntries: PreferenceEntries + preferenceEntryValues: PreferenceEntryValues + + onClicked: { + pluginPreferenceView.currentIndex = index + } + onBtnPreferenceClicked: { + console.log("edit preference ", preferenceName) + console.log("preference type ", preferenceType) + console.log("preference entry values ", preferenceEntryValues.length) + editPreferenceSlot(preferenceType, preferenceName, preferenceEntryValues) + } + } + } + } +} diff --git a/src/settingsview/components/PluginListSettingsView.qml b/src/settingsview/components/PluginListSettingsView.qml new file mode 100644 index 00000000..09434a31 --- /dev/null +++ b/src/settingsview/components/PluginListSettingsView.qml @@ -0,0 +1,200 @@ +/* + * Copyright (C) 2019-2020 by Savoir-faire Linux + * Author: Yang Wang + * + * 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 . + */ + +import QtQuick 2.15 +import QtQuick.Window 2.14 +import QtQuick.Controls 2.14 +import QtQuick.Controls.Universal 2.12 +import QtQuick.Layouts 1.3 +import Qt.labs.platform 1.1 +import QtGraphicalEffects 1.14 +import net.jami.Models 1.0 +import "../../commoncomponents" + +Rectangle { + id: pluginListSettingsViewRect + + property PluginListPreferencesView pluginListPreferencesView + visible: false + signal scrollView + + function updatePluginListDisplayed() { + // settings + } + + function openPluginFileSlot(){ + pluginPathDialog.open() + } + + function updateAndShowPluginsSlot() + { + pluginItemListModel.reset() + } + + function loadPluginSlot(pluginId, isLoaded){ + var loaded = false + if (isLoaded) + ClientWrapper.pluginModel.unloadPlugin(pluginId) + else + loaded = ClientWrapper.pluginModel.loadPlugin(pluginId) + if(pluginListPreferencesView.pluginId === pluginId) + pluginListPreferencesView.isLoaded = loaded + updateAndShowPluginsSlot() + } + + function openPreferencesPluginSlot(pluginName, pluginIcon, pluginId, isLoaded){ + updateAndShowPluginPreferenceSlot(pluginName, pluginIcon, pluginId, isLoaded) + } + + function updateAndShowPluginPreferenceSlot(pluginName, pluginIcon, pluginId, isLoaded){ + pluginListPreferencesView.pluginName = pluginName + pluginListPreferencesView.pluginIcon = pluginIcon + pluginListPreferencesView.pluginId = pluginId + pluginListPreferencesView.isLoaded = isLoaded + pluginListPreferencesView.updatePreferenceListDisplayed(!pluginListPreferencesView.visible) + pluginListPreferencesView.visible = !pluginListPreferencesView.visible + scrollView() + } + + JamiFileDialog { + id: pluginPathDialog + + mode: JamiFileDialog.OpenFile + title: qsTr("Select A Plugin to Install") + folder: StandardPaths.writableLocation(StandardPaths.DownloadLocation) + + nameFilters: [qsTr("Plugin Files") + " (*.jpl)", qsTr( + "All files") + " (*)"] + + onRejected: {} + + onVisibleChanged: { + if (!visible) { + rejected() + } + } + + onAccepted: { + var url = ClientWrapper.utilsAdaptor.getAbsPath(file.toString()) + ClientWrapper.pluginModel.installPlugin(url, true) + updateAndShowPluginsSlot() + } + } + + PluginItemListModel { + id: pluginItemListModel + } + + Layout.fillHeight: true + Layout.fillWidth: true + + ColumnLayout { + id: pluginListViewLayout + + Layout.fillHeight: true + Layout.maximumWidth: 580 + Layout.preferredWidth: 580 + Layout.minimumWidth: 580 + + Label { + Layout.fillWidth: true + Layout.minimumHeight: 25 + Layout.preferredHeight: 25 + Layout.maximumHeight: 25 + + text: qsTr("Installed plugins") + font.pointSize: 13 + font.kerning: true + + horizontalAlignment: Text.AlignLeft + verticalAlignment: Text.AlignVCenter + } + + ColumnLayout { + spacing: 6 + + Layout.fillWidth: true + Layout.topMargin: 6 + + HoverableRadiusButton { + id: installButton + + Layout.leftMargin: 20 + + Layout.maximumWidth: 320 + Layout.preferredWidth: 320 + Layout.minimumWidth: 320 + + Layout.minimumHeight: 30 + Layout.preferredHeight: 30 + Layout.maximumHeight: 30 + + radius: height / 2 + + text: qsTr("+ Install plugin") + fontPointSize: 10 + font.kerning: true + + onClicked: { + openPluginFileSlot() + } + } + + ListViewJami { + id: pluginListView + + Layout.leftMargin: 20 + + Layout.minimumWidth: 320 + Layout.preferredWidth: 320 + Layout.maximumWidth: 320 + + Layout.minimumHeight: 175 + Layout.preferredHeight: 175 + Layout.maximumHeight: 175 + + model: pluginItemListModel + + delegate: PluginItemDelegate{ + id: pluginItemDelegate + + width: pluginListView.width + height: 50 + + pluginName : PluginName + pluginId: PluginId + pluginIcon: PluginIcon + isLoaded: IsLoaded + + onClicked: { + pluginListView.currentIndex = index + } + + onBtnLoadPluginToggled:{ + loadPluginSlot(pluginId, isLoaded) + } + + onBtnPreferencesPluginClicked:{ + openPreferencesPluginSlot(pluginName, pluginIcon, pluginId, isLoaded) + } + } + } + } + } +} + \ No newline at end of file diff --git a/src/settingsview/components/PluginSettingsPage.qml b/src/settingsview/components/PluginSettingsPage.qml new file mode 100644 index 00000000..b71f7aa4 --- /dev/null +++ b/src/settingsview/components/PluginSettingsPage.qml @@ -0,0 +1,148 @@ +/* + * Copyright (C) 2019-2020 by Savoir-faire Linux + * Author: Yang Wang + * + * 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 . + */ + +import QtQuick 2.15 +import QtQuick.Window 2.14 +import QtQuick.Controls 2.14 +import QtQuick.Controls.Universal 2.12 +import QtQuick.Layouts 1.3 +import Qt.labs.platform 1.1 +import QtGraphicalEffects 1.14 +import net.jami.Models 1.0 +import "../../commoncomponents" + +Rectangle { + id: pluginSettingsRect + + function populatePluginSettings(){ + // settings + enabledplugin.checked = ClientWrapper.pluginModel.getPluginsEnabled() + pluginListSettingsView.visible = enabledplugin.checked + if (pluginListSettingsView.visible) { + pluginListSettingsView.updatePluginListDisplayed() + } + } + + function slotSetPluginEnabled(state){ + ClientWrapper.pluginModel.setPluginsEnabled(state) + } + + Layout.fillHeight: true + Layout.fillWidth: true + + ColumnLayout { + anchors.fill: parent + spacing: 6 + + width: parent.width + height: parent.height + + Label { + width: parent.width + height: parent.height + + Layout.leftMargin: 35 + Layout.topMargin: 15 + Layout.alignment: Qt.AlignTop + + text: qsTr("Plugin") + + font.pointSize: 15 + font.kerning: true + + horizontalAlignment: Text.AlignBottom + verticalAlignment: Text.AlignVCenter + } + + ScrollView { + id: pluginScrollView + Layout.fillHeight: true + Layout.fillWidth: true + + width: parent.width + height: parent.height + focus: true + + clip: true + + ColumnLayout { + id: pluginViewLayout + Layout.fillHeight: true + Layout.fillWidth: true + + ToggleSwitch { + id: enabledplugin + + Layout.topMargin: 15 + Layout.leftMargin: 36 + + labelText: "Enable" + fontPointSize: 13 + + onSwitchToggled: { + slotSetPluginEnabled(checked) + + pluginListSettingsView.visible = checked + if (!checked) { + pluginListPreferencesView.visible = checked + } + if (pluginListSettingsView.visible) { + pluginListSettingsView.updatePluginListDisplayed() + } + } + } + ColumnLayout { + spacing: 6 + Layout.fillHeight: true + width:380 + height:100 + + // instantiate plugin list setting page + PluginListSettingsView { + id: pluginListSettingsView + + width:380 + height:265 + Layout.leftMargin: 35 + Layout.topMargin: 15 + Layout.alignment: Qt.AlignHCenter + + pluginListPreferencesView: pluginListPreferencesView + + onScrollView:{ } + } + + PluginListPreferencesView { + id: pluginListPreferencesView + + width:380 + Layout.minimumHeight: 175 + Layout.preferredHeight: height + Layout.maximumHeight: 1000 + Layout.alignment: Qt.AlignHCenter + Layout.leftMargin: 55 + + onUpdatePluginList:{ + pluginListSettingsView.updateAndShowPluginsSlot() + } + } + } + } + } + } +} diff --git a/src/settingsview/components/PreferenceItemDelegate.qml b/src/settingsview/components/PreferenceItemDelegate.qml new file mode 100644 index 00000000..88574f27 --- /dev/null +++ b/src/settingsview/components/PreferenceItemDelegate.qml @@ -0,0 +1,102 @@ +/* + * Copyright (C) 2019-2020 by Savoir-faire Linux + * Author: Yang Wang + * + * 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 . + */ + +import QtQuick 2.15 +import QtQuick.Window 2.15 +import QtQuick.Controls 2.15 +import QtQuick.Controls.Universal 2.12 +import QtQuick.Layouts 1.3 +import QtGraphicalEffects 1.14 +import QtQuick.Controls.Styles 1.4 +import net.jami.Models 1.0 + +import "../../commoncomponents" + +ItemDelegate { + id: preferenceItemDelegate + + property string preferenceKey: "" + property string preferenceName: "" + property string preferenceSummary: "" + property int preferenceType: -1 + property string preferenceDefaultValue: "" + property var preferenceEntries: [] + property var preferenceEntryValues: [] + property string preferenceNewValue: "" + + signal btnPreferenceClicked + + highlighted: ListView.isCurrentItem + + RowLayout{ + anchors.fill: parent + + ColumnLayout{ + Layout.fillWidth: true + Layout.fillHeight: true + + Layout.topMargin: 7 + Layout.bottomMargin: 7 + Layout.leftMargin: 7 + + Layout.minimumHeight: 30 + + Label{ + Layout.minimumHeight: 10 + width: 320 - 36 + + font.pointSize: 10 + font.kerning: true + font.bold: true + text: preferenceName + } + } + + HoverableRadiusButton{ + id: btnPreference + + Layout.alignment: Qt.AlignRight + Layout.bottomMargin: 7 + Layout.rightMargin: 7 + + Layout.minimumWidth: 30 + Layout.preferredWidth: 30 + Layout.maximumWidth: 30 + + Layout.minimumHeight: 30 + Layout.preferredHeight: 30 + Layout.maximumHeight: 30 + + buttonImageHeight: height + buttonImageWidth: height + + source:{ + return "qrc:/images/icons/round-settings-24px.svg" + } + + ToolTip.visible: isHovering + ToolTip.text: { + return qsTr("Modify preference") + } + + onClicked: { + btnPreferenceClicked() + } + } + } +} diff --git a/src/settingsview/components/RevokeDevicePasswordDialog.qml b/src/settingsview/components/RevokeDevicePasswordDialog.qml new file mode 100644 index 00000000..69d433f9 --- /dev/null +++ b/src/settingsview/components/RevokeDevicePasswordDialog.qml @@ -0,0 +1,193 @@ +/* + * Copyright (C) 2020 by Savoir-faire Linux + * Author: Yang Wang + * + * 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 . + */ + +import QtQuick 2.15 +import QtQuick.Controls 2.14 +import QtQuick.Layouts 1.14 +import QtQuick.Controls.Styles 1.4 + +import "../../commoncomponents" + +Dialog { + id: revokeDevicePasswordDialog + + property string deviceId : "" + + signal revokeDeviceWithPassword(string idOfDevice, string password) + + function openRevokeDeviceDialog(deviceIdIn){ + deviceId = deviceIdIn + passwordEdit.clear() + revokeDevicePasswordDialog.open() + } + + visible: false + + anchors.centerIn: parent.Center + x: (parent.width - width) / 2 + y: (parent.height - height) / 2 + + title: qsTr("Enter this account's password to confirm the removal of this device") + + onClosed: { + reject() + } + + onAccepted:{ + revokeDeviceWithPassword(deviceId,passwordEdit.text) + } + + contentItem: Rectangle{ + implicitWidth: 365 + implicitHeight: 120 + + ColumnLayout{ + anchors.fill: parent + spacing: 7 + + Layout.alignment: Qt.AlignHCenter | Qt.AlignVCenter + + Item{ + Layout.fillHeight: true + + Layout.maximumWidth: 20 + Layout.preferredWidth: 20 + Layout.minimumWidth: 20 + } + + InfoLineEdit{ + id: passwordEdit + + Layout.alignment: Qt.AlignHCenter + + Layout.minimumWidth: 294 + Layout.preferredWidth: 294 + + Layout.preferredHeight: 30 + Layout.minimumHeight: 30 + + echoMode: TextInput.Password + + placeholderText: qsTr("Password") + } + + Item{ + Layout.fillHeight: true + + Layout.maximumWidth: 20 + Layout.preferredWidth: 20 + Layout.minimumWidth: 20 + } + + RowLayout{ + spacing: 7 + + Layout.alignment: Qt.AlignHCenter + + Layout.fillWidth: true + + Item{ + Layout.fillWidth: true + + Layout.maximumHeight: 20 + Layout.preferredHeight: 20 + Layout.minimumHeight: 20 + } + + HoverableRadiusButton{ + id: btnOkay + + Layout.maximumWidth: 130 + Layout.preferredWidth: 130 + Layout.minimumWidth: 130 + + Layout.maximumHeight: 30 + Layout.preferredHeight: 30 + Layout.minimumHeight: 30 + + radius: height /2 + + text: qsTr("Okay") + font.pointSize: 10 + font.kerning: true + + onClicked: { + accept() + } + } + + Item{ + Layout.fillWidth: true + Layout.minimumWidth: 40 + + Layout.maximumHeight: 20 + Layout.preferredHeight: 20 + Layout.minimumHeight: 20 + } + + HoverableButtonTextItem { + id: btnCancel + + Layout.maximumWidth: 130 + Layout.preferredWidth: 130 + Layout.minimumWidth: 130 + + Layout.maximumHeight: 30 + Layout.preferredHeight: 30 + Layout.minimumHeight: 30 + + backgroundColor: "red" + onEnterColor: Qt.rgba(150 / 256, 0, 0, 0.7) + onDisabledBackgroundColor: Qt.rgba( + 255 / 256, + 0, 0, 0.8) + onPressColor: backgroundColor + textColor: "white" + + radius: height /2 + + text: qsTr("Cancel") + font.pointSize: 10 + font.kerning: true + + onClicked: { + reject() + } + } + + Item{ + Layout.fillWidth: true + Layout.minimumWidth: 40 + + Layout.maximumHeight: 20 + Layout.preferredHeight: 20 + Layout.minimumHeight: 20 + } + + } + + Item{ + Layout.fillHeight: true + + Layout.maximumWidth: 20 + Layout.preferredWidth: 20 + Layout.minimumWidth: 20 + } + } + } +} diff --git a/src/settingsview/components/SettingParaCombobox.qml b/src/settingsview/components/SettingParaCombobox.qml new file mode 100644 index 00000000..b691acb2 --- /dev/null +++ b/src/settingsview/components/SettingParaCombobox.qml @@ -0,0 +1,110 @@ +/* + * Copyright (C) 2019-2020 by Savoir-faire Linux + * Author: Yang Wang + * + * 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 . + */ + +import QtQuick 2.15 +import QtQuick.Window 2.15 +import QtQuick.Controls 2.15 +import QtQuick.Controls.Universal 2.12 +import QtQuick.Layouts 1.3 +import QtGraphicalEffects 1.14 +import QtQuick.Controls.Styles 1.4 + +ComboBox { + id: control + + delegate: ItemDelegate { + width: control.width + contentItem: Text { + text: { + var currentItem = control.delegateModel.items.get(index) + return currentItem.model[control.textRole].toString() + } + color: "black" + font: control.font + elide: Text.ElideRight + verticalAlignment: Text.AlignVCenter + } + highlighted: control.highlightedIndex === index + } + + indicator: Canvas { + id: canvas + x: control.width - width - control.rightPadding + y: control.topPadding + (control.availableHeight - height) / 2 + width: 12 + height: 8 + contextType: "2d" + + Connections { + target: control + function onPressedChanged(){ + canvas.requestPaint() + } + } + + onPaint: { + context.reset(); + context.moveTo(0, 0); + context.lineTo(width, 0); + context.lineTo(width / 2, height); + context.closePath(); + context.fillStyle = control.pressed ? "#17a81a" : "#21be2b"; + context.fill(); + } + } + + contentItem: Text { + leftPadding: 0 + rightPadding: control.indicator.width + control.spacing + + text: control.displayText + font: control.font + color: "black" + verticalAlignment: Text.AlignVCenter + elide: Text.ElideRight + } + + background: Rectangle { + implicitWidth: 120 + implicitHeight: 40 + border.color: "white" + border.width: control.visualFocus ? 2 : 1 + radius: 2 + } + + popup: Popup { + y: control.height - 1 + width: control.width + implicitHeight: contentItem.implicitHeight + padding: 1 + + contentItem: ListView { + clip: true + implicitHeight: contentHeight + model: control.delegateModel + currentIndex: control.highlightedIndex + + ScrollIndicator.vertical: ScrollIndicator { } + } + + background: Rectangle { + border.color: "gray" + radius: 2 + } + } +} diff --git a/src/settingsview/components/ToggleSwitch.qml b/src/settingsview/components/ToggleSwitch.qml new file mode 100644 index 00000000..27c84bdc --- /dev/null +++ b/src/settingsview/components/ToggleSwitch.qml @@ -0,0 +1,74 @@ +/* + * Copyright (C) 2019-2020 by Savoir-faire Linux + * Author: Yang Wang + * + * 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 . + */ + +import QtQuick 2.15 +import QtQuick.Window 2.14 +import QtQuick.Controls 2.14 +import QtQuick.Controls.Universal 2.12 +import QtQuick.Layouts 1.3 +import QtGraphicalEffects 1.14 +import QtQuick.Controls.Styles 1.4 + +RowLayout { + property string labelText: value + property int widthOfSwitch: 50 + property int heightOfSwitch: 10 + property int heightOfLayout: 30 + property int fontPointSize: 13 + + property alias toggleSwitch: switchOfLayout + property alias checked: switchOfLayout.checked + + signal switchToggled + + spacing: 18 + Layout.fillWidth: true + Layout.maximumHeight: 30 + + Switch { + id: switchOfLayout + Layout.alignment: Qt.AlignVCenter + + Layout.maximumWidth: widthOfSwitch + Layout.preferredWidth: widthOfSwitch + Layout.minimumWidth: widthOfSwitch + + Layout.minimumHeight: heightOfSwitch + Layout.preferredHeight: heightOfSwitch + Layout.maximumHeight: heightOfSwitch + + onToggled: { + switchToggled() + } + } + + Label { + Layout.fillWidth: true + + Layout.minimumHeight: heightOfLayout + Layout.preferredHeight: heightOfLayout + Layout.maximumHeight: heightOfLayout + + text: qsTr(labelText) + font.pointSize: fontPointSize + font.kerning: true + + horizontalAlignment: Text.AlignLeft + verticalAlignment: Text.AlignVCenter + } +} diff --git a/src/settingsview/components/VideoCodecDelegate.qml b/src/settingsview/components/VideoCodecDelegate.qml new file mode 100644 index 00000000..a01fd287 --- /dev/null +++ b/src/settingsview/components/VideoCodecDelegate.qml @@ -0,0 +1,100 @@ +/* + * Copyright (C) 2019-2020 by Savoir-faire Linux + * Author: Yang Wang + * + * 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 . + */ + +import QtQuick 2.15 +import QtQuick.Window 2.15 +import QtQuick.Controls 2.15 +import QtQuick.Controls.Universal 2.12 +import QtQuick.Layouts 1.3 +import QtGraphicalEffects 1.14 +import QtQuick.Controls.Styles 1.4 +import net.jami.Models 1.0 + +ItemDelegate { + id: videoCodecDelegate + + property string videoCodecName : "" + property bool isEnabled : false + property int videoCodecId + + signal videoCodecStateChange(string idToSet , bool isToBeEnabled) + + property int checkBoxWidth: 10 + + highlighted: ListView.isCurrentItem + + RowLayout{ + anchors.fill: parent + + spacing: 10 + + CheckBox{ + id: checkBoxIsEnabled + + Layout.leftMargin: 20 + + Layout.alignment: Qt.AlignLeft | Qt.AlignVCenter + Layout.fillHeight: true + + Layout.minimumWidth: checkBoxWidth + Layout.preferredWidth: checkBoxWidth + Layout.maximumWidth: checkBoxWidth + + tristate: false + checkState: isEnabled ? Qt.Checked : Qt.Unchecked + + indicator.implicitWidth: checkBoxWidth + indicator.implicitHeight:checkBoxWidth + + indicator.layer.textureSize.width: checkBoxWidth + indicator.layer.textureSize.height: checkBoxWidth + + text: "" + + nextCheckState: function() { + var result + var result_bool + + if (checkState === Qt.Checked){ + result = Qt.Unchecked + result_bool = false + } else { + result = Qt.Checked + result_bool = true + } + videoCodecStateChange(videoCodecId,result_bool) + return result + } + } + + Label{ + id: formatNameLabel + + Layout.alignment: Qt.AlignLeft | Qt.AlignVCenter + horizontalAlignment: Text.AlignLeft + verticalAlignment: Text.AlignVCenter + + Layout.fillWidth: true + Layout.fillHeight: true + + text: videoCodecName + font.pointSize: 8 + font.kerning: true + } + } +} diff --git a/src/smartlistmodel.cpp b/src/smartlistmodel.cpp new file mode 100644 index 00000000..8fd0d5cb --- /dev/null +++ b/src/smartlistmodel.cpp @@ -0,0 +1,383 @@ +/* + * Copyright (C) 2017-2020 by Savoir-faire Linux + * Author: Anthony Léonard + * Author: Andreas Traczyk + * Author: Mingrui Zhang + * + * 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 . + */ + +#include "smartlistmodel.h" + +#include "lrcinstance.h" +#include "pixbufmanipulator.h" +#include "utils.h" + +#include "api/contactmodel.h" +#include "globalinstances.h" + +#include + +SmartListModel::SmartListModel(const QString &accId, + QObject *parent, + SmartListModel::Type listModelType, + const QString &convUid) + : QAbstractListModel(parent) + , accountId_(accId) + , listModelType_(listModelType) + , convUid_(convUid) +{ + if (listModelType_ == Type::CONFERENCE) { + setConferenceableFilter(); + } +} + +SmartListModel::~SmartListModel() {} + +int +SmartListModel::rowCount(const QModelIndex &parent) const +{ + if (!parent.isValid()) { + auto &accInfo = LRCInstance::accountModel().getAccountInfo(accountId_); + auto &convModel = accInfo.conversationModel; + if (listModelType_ == Type::TRANSFER) { + auto filterType = accInfo.profileInfo.type; + return convModel->getFilteredConversations(filterType).size(); + } else if (listModelType_ == Type::CONFERENCE) { + auto calls = conferenceables_[ConferenceableItem::CALL]; + auto contacts = conferenceables_[ConferenceableItem::CONTACT]; + auto rowCount = contacts.size(); + if (calls.size()) { + rowCount = 2; + rowCount += sectionState_[tr("Calls")] ? calls.size() : 0; + rowCount += sectionState_[tr("Contacts")] ? contacts.size() : 0; + } + return rowCount; + } + return accInfo.conversationModel->allFilteredConversations().size(); + } + return 0; +} + +int +SmartListModel::columnCount(const QModelIndex &parent) const +{ + Q_UNUSED(parent); + return 1; +} + +QVariant +SmartListModel::data(const QModelIndex &index, int role) const +{ + if (!index.isValid()) { + return QVariant(); + } + + try { + auto &accountInfo = LRCInstance::accountModel().getAccountInfo(accountId_); + auto &convModel = accountInfo.conversationModel; + lrc::api::conversation::Info item; + if (listModelType_ == Type::TRANSFER) { + auto filterType = accountInfo.profileInfo.type; + item = convModel->getFilteredConversations(filterType).at(index.row()); + return getConversationItemData(item, accountInfo, role); + } else if (listModelType_ == Type::CONFERENCE) { + auto calls = conferenceables_[ConferenceableItem::CALL]; + auto contacts = conferenceables_[ConferenceableItem::CONTACT]; + QString itemConvUid{}, itemAccId{}; + if (calls.size() == 0) { + itemConvUid = contacts.at(index.row()).at(0).convId; + itemAccId = contacts.at(index.row()).at(0).accountId; + } else { + bool callsOpen = sectionState_[tr("Calls")]; + bool contactsOpen = sectionState_[tr("Contacts")]; + auto callSectionEnd = callsOpen ? calls.size() + 1 : 1; + auto contactSectionEnd = contactsOpen ? callSectionEnd + contacts.size() + 1 + : callSectionEnd + 1; + if (index.row() < callSectionEnd) { + if (index.row() == 0) { + return QVariant(role == Role::SectionName + ? (callsOpen ? "➖ " : "➕ ") + QString(tr("Calls")) + : ""); + } else { + auto idx = index.row() - 1; + itemConvUid = calls.at(idx).at(0).convId; + itemAccId = calls.at(idx).at(0).accountId; + } + } else if (index.row() < contactSectionEnd) { + if (index.row() == callSectionEnd) { + return QVariant(role == Role::SectionName + ? (contactsOpen ? "➖ " : "➕ ") + QString(tr("Contacts")) + : ""); + } else { + auto idx = index.row() - (callSectionEnd + 1); + itemConvUid = contacts.at(idx).at(0).convId; + itemAccId = contacts.at(idx).at(0).accountId; + } + } + } + if (role == Role::AccountId) { + return QVariant(itemAccId); + } + item = LRCInstance::getConversationFromConvUid(itemConvUid, itemAccId); + auto &itemAccountInfo = LRCInstance::accountModel().getAccountInfo(itemAccId); + return getConversationItemData(item, itemAccountInfo, role); + } else if (listModelType_ == Type::CONVERSATION) { + item = convModel->filteredConversation(index.row()); + return getConversationItemData(item, accountInfo, role); + } + } catch (const std::exception &e) { + qWarning() << e.what(); + } + return QVariant(); +} + +QHash +SmartListModel::roleNames() const +{ + QHash roles; + roles[DisplayName] = "DisplayName"; + roles[DisplayID] = "DisplayID"; + roles[Picture] = "Picture"; + roles[Presence] = "Presence"; + roles[URI] = "URI"; + roles[UnreadMessagesCount] = "UnreadMessagesCount"; + roles[LastInteractionDate] = "LastInteractionDate"; + roles[LastInteraction] = "LastInteraction"; + roles[ContactType] = "ContactType"; + roles[UID] = "UID"; + roles[InCall] = "InCall"; + roles[IsAudioOnly] = "IsAudioOnly"; + roles[CallStackViewShouldShow] = "CallStackViewShouldShow"; + roles[CallStateStr] = "CallStateStr"; + roles[SectionName] = "SectionName"; + roles[AccountId] = "AccountId"; + roles[Draft] = "Draft"; + return roles; +} + +void +SmartListModel::setConferenceableFilter(const QString &filter) +{ + beginResetModel(); + auto &accountInfo = LRCInstance::accountModel().getAccountInfo(accountId_); + auto &convModel = accountInfo.conversationModel; + conferenceables_ = convModel->getConferenceableConversations(convUid_, filter); + sectionState_[tr("Calls")] = true; + sectionState_[tr("Contacts")] = true; + endResetModel(); +} + +void +SmartListModel::toggleSection(const QString §ion) +{ + beginResetModel(); + if (section.contains(tr("Calls"))) { + sectionState_[tr("Calls")] ^= true; + } else if (section.contains(tr("Contacts"))) { + sectionState_[tr("Contacts")] ^= true; + } + endResetModel(); +} + +int +SmartListModel::currentUidSmartListModelIndex() +{ + auto convUid = LRCInstance::getCurrentConvUid(); + for (int i = 0; i < rowCount(); i++) { + if (convUid == data(index(i, 0), Role::UID)) + return i; + } + + return -1; +} + +QVariant +SmartListModel::getConversationItemData(const conversation::Info &item, + const account::Info &accountInfo, + int role) const +{ + if (item.participants.size() <= 0) { + return QVariant(); + } + auto &contactModel = accountInfo.contactModel; + switch (role) { + case Role::Picture: { + auto contactImage + = GlobalInstances::pixmapManipulator().decorationRole(item, accountInfo).value(); + return QString::fromLatin1(Utils::QImageToByteArray(contactImage).toBase64().data()); + } + case Role::DisplayName: { + if (!item.participants.isEmpty()) { + auto &contact = contactModel->getContact(item.participants[0]); + return QVariant(Utils::bestNameForContact(contact)); + } + return QVariant(""); + } + case Role::DisplayID: { + if (!item.participants.isEmpty()) { + auto &contact = contactModel->getContact(item.participants[0]); + return QVariant(Utils::bestIdForContact(contact)); + } + return QVariant(""); + } + case Role::Presence: { + if (!item.participants.isEmpty()) { + auto &contact = contactModel->getContact(item.participants[0]); + return QVariant(contact.isPresent); + } + return QVariant(false); + } + case Role::URI: { + if (!item.participants.isEmpty()) { + auto &contact = contactModel->getContact(item.participants[0]); + return QVariant(contact.profileInfo.uri); + } + return QVariant(""); + } + case Role::UnreadMessagesCount: + return QVariant(item.unreadMessages); + case Role::LastInteractionDate: { + if (!item.interactions.empty()) { + auto &date = item.interactions.at(item.lastMessageUid).timestamp; + return QVariant(QString::fromStdString(Utils::formatTimeString(date))); + } + return QVariant(""); + } + case Role::LastInteraction: { + if (!item.interactions.empty()) { + return QVariant(item.interactions.at(item.lastMessageUid).body); + } + return QVariant(""); + } + case Role::LastInteractionType: { + if (!item.interactions.empty()) { + return QVariant( + Utils::toUnderlyingValue(item.interactions.at(item.lastMessageUid).type)); + } + return QVariant(0); + } + case Role::ContactType: { + if (!item.participants.isEmpty()) { + auto &contact = contactModel->getContact(item.participants[0]); + return QVariant(Utils::toUnderlyingValue(contact.profileInfo.type)); + } + return QVariant(0); + } + case Role::UID: + return QVariant(item.uid); + case Role::InCall: { + auto &convInfo = LRCInstance::getConversationFromConvUid(item.uid); + if (!convInfo.uid.isEmpty()) { + auto callModel = LRCInstance::getCurrentCallModel(); + return QVariant(callModel->hasCall(convInfo.callId)); + } + return QVariant(false); + } + case Role::IsAudioOnly: { + auto &convInfo = LRCInstance::getConversationFromConvUid(item.uid); + if (!convInfo.uid.isEmpty()) { + auto call = LRCInstance::getCallInfoForConversation(convInfo); + if (call) { + return QVariant(call->isAudioOnly); + } + } + return QVariant(); + } + case Role::CallStackViewShouldShow: { + auto &convInfo = LRCInstance::getConversationFromConvUid(item.uid); + if (!convInfo.uid.isEmpty()) { + auto callModel = LRCInstance::getCurrentCallModel(); + auto call = callModel->getCall(convInfo.callId); + return QVariant(callModel->hasCall(convInfo.callId) + && ((!call.isOutgoing + && (call.status == lrc::api::call::Status::IN_PROGRESS + || call.status == lrc::api::call::Status::PAUSED)) + || call.isOutgoing)); + } + return QVariant(false); + } + case Role::CallStateStr: { + auto &convInfo = LRCInstance::getConversationFromConvUid(item.uid); + if (!convInfo.uid.isEmpty()) { + auto call = LRCInstance::getCallInfoForConversation(convInfo); + if (call) { + auto statusString = call::to_string(call->status); + return QVariant(statusString); + } + } + return QVariant(); + } + case Role::SectionName: + return QVariant(QString()); + case Role::Draft: { + if (!item.uid.isEmpty()) { + auto draft = LRCInstance::getContentDraft(item.uid, accountInfo.id); + if (!draft.isEmpty()) { + /* + * Pencil Emoji + */ + uint cp = 0x270F; + auto emojiString = QString::fromUcs4(&cp, 1); + return emojiString + LRCInstance::getContentDraft(item.uid, accountInfo.id); + } + } + return QVariant(""); + } + } + return QVariant(); +} + +QModelIndex +SmartListModel::index(int row, int column, const QModelIndex &parent) const +{ + Q_UNUSED(parent); + if (column != 0) { + return QModelIndex(); + } + + if (row >= 0 && row < rowCount()) { + return createIndex(row, column); + } + return QModelIndex(); +} + +QModelIndex +SmartListModel::parent(const QModelIndex &child) const +{ + Q_UNUSED(child); + return QModelIndex(); +} + +Qt::ItemFlags +SmartListModel::flags(const QModelIndex &index) const +{ + auto flags = QAbstractItemModel::flags(index) | Qt::ItemNeverHasChildren | Qt::ItemIsSelectable; + auto type = Utils::toEnum(data(index, Role::ContactType).value()); + auto uid = data(index, Role::UID).value(); + if (!index.isValid()) { + return QAbstractItemModel::flags(index); + } else if ((type == lrc::api::profile::Type::TEMPORARY && uid.isEmpty())) { + flags &= ~(Qt::ItemIsSelectable); + } + return flags; +} + +void +SmartListModel::setAccount(const QString &accountId) +{ + beginResetModel(); + accountId_ = accountId; + endResetModel(); +} diff --git a/src/smartlistmodel.h b/src/smartlistmodel.h new file mode 100644 index 00000000..8ae7dca2 --- /dev/null +++ b/src/smartlistmodel.h @@ -0,0 +1,99 @@ +/* + * Copyright (C) 2017-2020 by Savoir-faire Linux + * Author: Anthony Léonard + * Author: Andreas Traczyk + * Author: Mingrui Zhang + * + * 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 . + */ + +#pragma once + +#include "api/account.h" +#include "api/contact.h" +#include "api/conversation.h" +#include "api/conversationmodel.h" + +#include + +using namespace lrc::api; + +class SmartListModel : public QAbstractListModel +{ + Q_OBJECT +public: + using AccountInfo = lrc::api::account::Info; + using ConversationInfo = lrc::api::conversation::Info; + using ContactInfo = lrc::api::contact::Info; + + enum class Type { CONVERSATION, CONFERENCE, TRANSFER, COUNT__ }; + + enum Role { + DisplayName = Qt::UserRole + 1, + DisplayID, + Picture, + Presence, + URI, + UnreadMessagesCount, + LastInteractionDate, + LastInteraction, + LastInteractionType, + ContactType, + UID, + ContextMenuOpen, + InCall, + IsAudioOnly, + CallStackViewShouldShow, + CallStateStr, + SectionName, + AccountId, + Draft + }; + + explicit SmartListModel(const QString &accId, + QObject *parent = 0, + SmartListModel::Type listModelType = Type::CONVERSATION, + const QString &convUid = {}); + ~SmartListModel(); + + /* + * QAbstractListModel. + */ + int rowCount(const QModelIndex &parent = QModelIndex()) const override; + int columnCount(const QModelIndex &parent) const override; + QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override; + QHash roleNames() const override; + QModelIndex index(int row, int column = 0, const QModelIndex &parent = QModelIndex()) const; + QModelIndex parent(const QModelIndex &child) const; + Qt::ItemFlags flags(const QModelIndex &index) const; + + Q_INVOKABLE void setAccount(const QString &accId); + Q_INVOKABLE void setConferenceableFilter(const QString &filter = {}); + Q_INVOKABLE void toggleSection(const QString §ion); + Q_INVOKABLE int currentUidSmartListModelIndex(); + +private: + QString accountId_; + + QVariant getConversationItemData(const ConversationInfo &item, + const AccountInfo &accountInfo, + int role) const; + /* + * List sectioning. + */ + QString convUid_; + Type listModelType_; + QMap sectionState_; + QMap conferenceables_; +}; \ No newline at end of file diff --git a/src/tintedbuttonimageprovider.h b/src/tintedbuttonimageprovider.h new file mode 100644 index 00000000..384989be --- /dev/null +++ b/src/tintedbuttonimageprovider.h @@ -0,0 +1,61 @@ +/* + * Copyright (C) 2020 by Savoir-faire Linux + * Author: Mingrui Zhang + * + * 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 . + */ + +#pragma once + +#include "lrcinstance.h" +#include "utils.h" + +#include +#include +#include +#include +#include + +class TintedButtonImageProvider : public QObject, public QQuickImageProvider +{ +public: + TintedButtonImageProvider() + : QQuickImageProvider(QQuickImageProvider::Pixmap, + QQmlImageProviderBase::ForceAsynchronousImageLoading) + {} + + QPixmap + requestPixmap(const QString &id, QSize *size, const QSize &requestedSize) override + { + Q_UNUSED(size); + + QColor tintedColor; + + auto list = id.split('+', QString::SkipEmptyParts); + + if (list.size() == 2) { + QPixmap pixmapToSend(":/images/icons/" + list[0]); + if (!requestedSize.isEmpty()) { + pixmapToSend = pixmapToSend.scaled(requestedSize, Qt::KeepAspectRatio); + } else { + pixmapToSend = pixmapToSend.scaled(QSize(30, 30), Qt::KeepAspectRatio); + } + tintedColor.setNamedColor(list[1]); + + return Utils::generateTintedPixmap(pixmapToSend, tintedColor); + } + + return QPixmap(); + } +}; \ No newline at end of file diff --git a/src/utils.cpp b/src/utils.cpp new file mode 100644 index 00000000..a397cab7 --- /dev/null +++ b/src/utils.cpp @@ -0,0 +1,1082 @@ +/* + * Copyright (C) 2015-2020 by Savoir-faire Linux + * Author: Edric Ladent Milaret + * Author: Andreas Traczyk + * Author: Isa Nanic + * + * 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 . + */ + +#include "utils.h" + +#ifdef Q_OS_WIN +#include +#include +#include +#include +#include +#include +#endif + +#include "globalsystemtray.h" +#include "jamiavatartheme.h" +#include "lrcinstance.h" +#include "pixbufmanipulator.h" +#include "version.h" + +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +bool +Utils::CreateStartupLink(const std::wstring &wstrAppName) +{ +#ifdef Q_OS_WIN + TCHAR szPath[MAX_PATH]; + GetModuleFileName(NULL, szPath, MAX_PATH); + + std::wstring programPath(szPath); + + TCHAR startupPath[MAX_PATH]; + SHGetFolderPathW(NULL, CSIDL_STARTUP, NULL, 0, startupPath); + + std::wstring linkPath(startupPath); + linkPath += std::wstring(TEXT("\\") + wstrAppName + TEXT(".lnk")); + + return Utils::CreateLink(programPath.c_str(), linkPath.c_str()); +#else + return true; +#endif +} + +bool +Utils::CreateLink(LPCWSTR lpszPathObj, LPCWSTR lpszPathLink) +{ +#ifdef Q_OS_WIN + HRESULT hres; + IShellLink *psl; + + hres = CoCreateInstance(CLSID_ShellLink, + NULL, + CLSCTX_INPROC_SERVER, + IID_IShellLink, + (LPVOID *) &psl); + if (SUCCEEDED(hres)) { + IPersistFile *ppf; + psl->SetPath(lpszPathObj); + psl->SetArguments(TEXT("--minimized")); + + hres = psl->QueryInterface(IID_IPersistFile, (LPVOID *) &ppf); + if (SUCCEEDED(hres)) { + hres = ppf->Save(lpszPathLink, TRUE); + ppf->Release(); + } + psl->Release(); + } + return hres; +#else + Q_UNUSED(lpszPathObj) + Q_UNUSED(lpszPathLink) + return true; +#endif +} + +void +Utils::DeleteStartupLink(const std::wstring &wstrAppName) +{ +#ifdef Q_OS_WIN + TCHAR startupPath[MAX_PATH]; + SHGetFolderPathW(NULL, CSIDL_STARTUP, NULL, 0, startupPath); + + std::wstring linkPath(startupPath); + linkPath += std::wstring(TEXT("\\") + wstrAppName + TEXT(".lnk")); + + DeleteFile(linkPath.c_str()); +#endif +} + +bool +Utils::CheckStartupLink(const std::wstring &wstrAppName) +{ +#ifdef Q_OS_WIN + TCHAR startupPath[MAX_PATH]; + SHGetFolderPathW(NULL, CSIDL_STARTUP, NULL, 0, startupPath); + + std::wstring linkPath(startupPath); + linkPath += std::wstring(TEXT("\\") + wstrAppName + TEXT(".lnk")); + return PathFileExists(linkPath.c_str()); +#else + return true; +#endif +} + +const char * +Utils::WinGetEnv(const char *name) +{ +#ifdef Q_OS_WIN + const DWORD buffSize = 65535; + static char buffer[buffSize]; + if (GetEnvironmentVariableA(name, buffer, buffSize)) { + return buffer; + } else { + return 0; + } +#else + return 0; +#endif +} + +void +Utils::removeOldVersions() +{ +#ifdef Q_OS_WIN + /* + * As per: https://git.jami.net/savoirfairelinux/ring-client-windows/issues/429 + * NB: As only the 64-bit version of this application is distributed, we will only + * remove 1. the configuration reg keys for Ring-x64, 2. the startup links for Ring, + * 3. the winsparkle reg keys. The NSIS uninstall reg keys for Jami-x64 are removed + * by the MSI installer. + * Uninstallation of Ring, either 32 or 64 bit, is left to the user. + * The current version of Jami will attempt to kill Ring.exe upon start if a startup + * link is found. + */ + QString node64 = "HKEY_LOCAL_MACHINE\\SOFTWARE\\WOW6432Node"; + QString hkcuSoftwareKey = "HKEY_CURRENT_USER\\Software\\"; + QString uninstKey = "\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\"; + QString company = "Savoir-Faire Linux"; + + /* + * 1. Configuration reg keys for Ring-x64. + */ + QSettings(hkcuSoftwareKey + "jami.net\\Ring", QSettings::NativeFormat).remove(""); + QSettings(hkcuSoftwareKey + "ring.cx", QSettings::NativeFormat).remove(""); + /* + * 2. Unset Ring as a startup application. + */ + if (Utils::CheckStartupLink(TEXT("Ring"))) { + qDebug() << "Found startup link for Ring. Removing it and killing Ring.exe."; + Utils::DeleteStartupLink(TEXT("Ring")); + QProcess::execute("taskkill /im Ring.exe /f"); + } + /* + * 3. Remove registry entries for winsparkle(both Jami-x64 and Ring-x64). + */ + QSettings(hkcuSoftwareKey + company, QSettings::NativeFormat).remove(""); +#else + return; +#endif +} + +QString +Utils::GetRingtonePath() +{ +#ifdef Q_OS_WIN + TCHAR workingDirectory[MAX_PATH]; + GetCurrentDirectory(MAX_PATH, workingDirectory); + + QString ringtonePath = QString::fromWCharArray(workingDirectory); + ringtonePath += QStringLiteral("\\ringtones\\default.opus"); + return ringtonePath; +#else + return QString("/usr/local"); +#endif +} + +QString +Utils::GenGUID() +{ +#ifdef Q_OS_WIN + GUID gidReference; + wchar_t *str; + HRESULT hCreateGuid = CoCreateGuid(&gidReference); + if (hCreateGuid == S_OK) { + StringFromCLSID(gidReference, &str); + auto gStr = QString::fromWCharArray(str); + return gStr.remove("{").remove("}").toLower(); + } else + return QString(); +#else + return QString(""); +#endif +} + +QString +Utils::GetISODate() +{ +#ifdef Q_OS_WIN + SYSTEMTIME lt; + GetSystemTime(<); + return QString("%1-%2-%3T%4:%5:%6Z") + .arg(lt.wYear) + .arg(lt.wMonth, 2, 10, QChar('0')) + .arg(lt.wDay, 2, 10, QChar('0')) + .arg(lt.wHour, 2, 10, QChar('0')) + .arg(lt.wMinute, 2, 10, QChar('0')) + .arg(lt.wSecond, 2, 10, QChar('0')); +#else + return QString(); +#endif +} + +void +Utils::InvokeMailto(const QString &subject, const QString &body, const QString &attachement) +{ +#ifdef Q_OS_WIN + HKEY hKey; + LONG lRes = RegOpenKeyExW(HKEY_CLASSES_ROOT, L"mailto", 0, KEY_READ, &hKey); + if (lRes != ERROR_FILE_NOT_FOUND) { + auto addr = QString("mailto:?subject=%1&body=%2").arg(subject).arg(body); + if (not attachement.isEmpty()) + addr += QString("&attachement=%1").arg(attachement); + ShellExecute(nullptr, L"open", addr.toStdWString().c_str(), NULL, NULL, SW_SHOWNORMAL); + } else { + QErrorMessage errorMessage; + errorMessage.showMessage(QObject::tr("No default mail client found")); + } +#endif +} + +QString +Utils::getContactImageString(const QString &accountId, const QString &uid) +{ + return QString::fromLatin1( + Utils::QImageToByteArray( + Utils::conversationPhoto(uid, LRCInstance::getAccountInfo(accountId))) + .toBase64() + .data()); +} + +QImage +Utils::getCirclePhoto(const QImage original, int sizePhoto) +{ + QImage target(sizePhoto, sizePhoto, QImage::Format_ARGB32_Premultiplied); + target.fill(Qt::transparent); + + QPainter painter(&target); + painter.setRenderHints(QPainter::Antialiasing | QPainter::SmoothPixmapTransform); + painter.setBrush(QBrush(Qt::white)); + auto scaledPhoto = original + .scaled(sizePhoto, + sizePhoto, + Qt::KeepAspectRatioByExpanding, + Qt::SmoothTransformation) + .convertToFormat(QImage::Format_ARGB32_Premultiplied); + int margin = 0; + if (scaledPhoto.width() > sizePhoto) { + margin = (scaledPhoto.width() - sizePhoto) / 2; + } + painter.drawEllipse(0, 0, sizePhoto, sizePhoto); + painter.setCompositionMode(QPainter::CompositionMode_SourceIn); + painter.drawImage(0, 0, scaledPhoto, margin, 0); + return target; +} + +void +Utils::setStackWidget(QStackedWidget *stack, QWidget *widget) +{ + if (stack->indexOf(widget) != -1 && stack->currentWidget() != widget) { + stack->setCurrentWidget(widget); + } +} + +void +Utils::showSystemNotification(QWidget *widget, + const QString &message, + long delay, + const QString &triggeredAccountId) +{ + QSettings settings("jami.net", "Jami"); + if (settings.value(SettingsKey::enableNotifications).toBool()) { + GlobalSystemTray::instance().setTriggeredAccountId(triggeredAccountId); + GlobalSystemTray::instance().showMessage(message, "", QIcon(":images/jami.png")); + QApplication::alert(widget, delay); + } +} + +void +Utils::showSystemNotification(QWidget *widget, + const QString &sender, + const QString &message, + long delay, + const QString &triggeredAccountId) +{ + QSettings settings("jami.net", "Jami"); + if (settings.value(SettingsKey::enableNotifications).toBool()) { + GlobalSystemTray::instance().setTriggeredAccountId(triggeredAccountId); + GlobalSystemTray::instance().showMessage(sender, message, QIcon(":images/jami.png")); + QApplication::alert(widget, delay); + } +} + +QSize +Utils::getRealSize(QScreen *screen) +{ +#ifdef Q_OS_WIN + DEVMODE dmThisScreen; + ZeroMemory(&dmThisScreen, sizeof(dmThisScreen)); + EnumDisplaySettings((const wchar_t *) screen->name().utf16(), + ENUM_CURRENT_SETTINGS, + (DEVMODE *) &dmThisScreen); + return QSize(dmThisScreen.dmPelsWidth, dmThisScreen.dmPelsHeight); +#else + return {}; +#endif +} + +void +Utils::forceDeleteAsync(const QString &path) +{ + /* + * Keep deleting file until the process holding it let go, + * or the file itself does not exist anymore. + */ + QtConcurrent::run([path] { + QFile file(path); + if (!QFile::exists(path)) + return; + int retries{0}; + while (!file.remove() && retries < 5) { + qDebug().noquote() << "\n" << file.errorString() << "\n"; + QThread::msleep(10); + ++retries; + } + }); +} + +UtilsAdapter & +UtilsAdapter::instance() +{ + static auto instance = new UtilsAdapter; + return *instance; +} + +QString +Utils::getChangeLog() +{ + QString logs; + QFile changeLogFile(":/changelog.html"); + if (!changeLogFile.open(QIODevice::ReadOnly | QIODevice::Text)) { + qDebug().noquote() << " Change log file failed to load"; + return {}; + } + QTextStream in(&changeLogFile); + in.setCodec("UTF-8"); + while (!in.atEnd()) { + logs += in.readLine(); + } + return logs; +} + +QString +Utils::getProjectCredits() +{ + QString credits; + QFile projectCreditsFile(":/projectcredits.html"); + if (!projectCreditsFile.open(QIODevice::ReadOnly | QIODevice::Text)) { + qDebug().noquote() << " Project Credits failed to load"; + return {}; + } + QTextStream in(&projectCreditsFile); + in.setCodec("UTF-8"); + while (!in.atEnd()) { + QString currentLine = in.readLine(); + if (credits.isEmpty()) { + credits += "

" + + UtilsAdapter::tr("Created by:") + "

"; + } else if (currentLine.contains("Marianne Forget")) { + credits + += "

") + + "" + UtilsAdapter::tr("Artwork by:") + + "

"; + } + credits += currentLine; + } + credits += "

") + + UtilsAdapter::tr("Based on the SFLPhone project") + "

"; + + return credits; +} + +void +Utils::cleanUpdateFiles() +{ + /* + * Delete all logs and msi in the %TEMP% directory before launching. + */ + QString dir = QString(Utils::WinGetEnv("TEMP")); + QDir log_dir(dir, {"jami*.log"}); + for (const QString &filename : log_dir.entryList()) { + log_dir.remove(filename); + } + QDir msi_dir(dir, {"jami*.msi"}); + for (const QString &filename : msi_dir.entryList()) { + msi_dir.remove(filename); + } + QDir version_dir(dir, {"version"}); + for (const QString &filename : version_dir.entryList()) { + version_dir.remove(filename); + } +} + +void +Utils::checkForUpdates(bool withUI, QWidget *parent) +{ + Q_UNUSED(withUI) + Q_UNUSED(parent) + /* + * TODO: check update logic. + */ +} + +void +Utils::applyUpdates(bool updateToBeta, QWidget *parent) +{ + Q_UNUSED(updateToBeta) + Q_UNUSED(parent) + /* + * TODO: update logic. + */ +} + +inline QString +removeEndlines(const QString &str) +{ + QString trimmed(str); + trimmed.remove(QChar('\n')); + trimmed.remove(QChar('\r')); + return trimmed; +} + +QString +Utils::bestIdForConversation(const lrc::api::conversation::Info &conv, + const lrc::api::ConversationModel &model) +{ + auto contact = model.owner.contactModel->getContact(conv.participants[0]); + if (!contact.registeredName.isEmpty()) { + return removeEndlines(contact.registeredName); + } + return removeEndlines(contact.profileInfo.uri); +} + +QString +Utils::bestIdForAccount(const lrc::api::account::Info &account) +{ + if (!account.registeredName.isEmpty()) { + return removeEndlines(account.registeredName); + } + return removeEndlines(account.profileInfo.uri); +} + +QString +Utils::bestNameForAccount(const lrc::api::account::Info &account) +{ + if (account.profileInfo.alias.isEmpty()) { + return bestIdForAccount(account); + } + return account.profileInfo.alias; +} + +QString +Utils::bestIdForContact(const lrc::api::contact::Info &contact) +{ + if (!contact.registeredName.isEmpty()) { + return removeEndlines(contact.registeredName); + } + return removeEndlines(contact.profileInfo.uri); +} + +QString +Utils::bestNameForContact(const lrc::api::contact::Info &contact) +{ + auto alias = removeEndlines(contact.profileInfo.alias); + if (alias.length() == 0) { + return bestIdForContact(contact); + } + return alias; +} + +QString +Utils::bestNameForConversation(const lrc::api::conversation::Info &conv, + const lrc::api::ConversationModel &model) +{ + try { + auto contact = model.owner.contactModel->getContact(conv.participants[0]); + auto alias = removeEndlines(contact.profileInfo.alias); + if (alias.length() == 0) { + return bestIdForConversation(conv, model); + } + return alias; + } catch (...) { + } + return {}; +} + +/* + * Returns empty string if only infoHash is available, second best identifier otherwise. + */ +QString +Utils::secondBestNameForAccount(const lrc::api::account::Info &account) +{ + auto alias = removeEndlines(account.profileInfo.alias); + auto registeredName = removeEndlines(account.registeredName); + auto infoHash = account.profileInfo.uri; + + if (!alias.length() == 0) { + /* + * If alias exists. + */ + if (!registeredName.length() == 0) { + /* + * If registeredName exists. + */ + return registeredName; + } else { + return infoHash; + } + } else { + if (!registeredName.length() == 0) { + /* + * If registeredName exists. + */ + return infoHash; + } else { + return ""; + } + } +} + +lrc::api::profile::Type +Utils::profileType(const lrc::api::conversation::Info &conv, + const lrc::api::ConversationModel &model) +{ + try { + auto contact = model.owner.contactModel->getContact(conv.participants[0]); + return contact.profileInfo.type; + } catch (...) { + return lrc::api::profile::Type::INVALID; + } +} + +std::string +Utils::formatTimeString(const std::time_t ×tamp) +{ + std::time_t now = std::time(nullptr); + char interactionDay[64]; + char nowDay[64]; + std::strftime(interactionDay, sizeof(interactionDay), "%D", std::localtime(×tamp)); + std::strftime(nowDay, sizeof(nowDay), "%D", std::localtime(&now)); + if (std::string(interactionDay) == std::string(nowDay)) { + char interactionTime[64]; + std::strftime(interactionTime, sizeof(interactionTime), "%R", std::localtime(×tamp)); + return interactionTime; + } else { + return interactionDay; + } +} + +bool +Utils::isInteractionGenerated(const lrc::api::interaction::Type &type) +{ + return type == lrc::api::interaction::Type::CALL + || type == lrc::api::interaction::Type::CONTACT; +} + +bool +Utils::isContactValid(const QString &contactUid, const lrc::api::ConversationModel &model) +{ + auto contact = model.owner.contactModel->getContact(contactUid); + return (contact.profileInfo.type == lrc::api::profile::Type::PENDING + || contact.profileInfo.type == lrc::api::profile::Type::TEMPORARY + || contact.profileInfo.type == lrc::api::profile::Type::RING + || contact.profileInfo.type == lrc::api::profile::Type::SIP) + && !contact.profileInfo.uri.isEmpty(); +} + +bool +Utils::getReplyMessageBox(QWidget *widget, const QString &title, const QString &text) +{ + if (QMessageBox::question(widget, title, text, QMessageBox::Yes | QMessageBox::No) + == QMessageBox::Yes) + return true; + return false; +} + +QImage +Utils::conversationPhoto(const QString &convUid, + const lrc::api::account::Info &accountInfo, + bool filtered) +{ + auto convInfo = LRCInstance::getConversationFromConvUid(convUid, accountInfo.id, filtered); + if (!convInfo.uid.isEmpty()) { + return GlobalInstances::pixmapManipulator() + .decorationRole(convInfo, accountInfo) + .value(); + } + return QImage(); +} + +QColor +Utils::getAvatarColor(const QString &canonicalUri) +{ + if (canonicalUri.isEmpty()) { + return JamiAvatarTheme::defaultAvatarColor_; + } + auto h = QString( + QCryptographicHash::hash(canonicalUri.toLocal8Bit(), QCryptographicHash::Md5).toHex()); + if (h.isEmpty() || h.isNull()) { + return JamiAvatarTheme::defaultAvatarColor_; + } + auto colorIndex = std::string("0123456789abcdef").find(h.at(0).toLatin1()); + return JamiAvatarTheme::avatarColors_[colorIndex]; +} + +/* Generate a QImage representing a dummy user avatar, when user doesn't provide it. + * Current rendering is a flat colored circle with a centered letter. + * The color of the letter is computed from the circle color to be visible whaterver be the circle color. + */ +QImage +Utils::fallbackAvatar(const QSize size, const QString &canonicalUriStr, const QString &letterStr) +{ + /* + * We start with a transparent avatar. + */ + QImage avatar(size, QImage::Format_ARGB32); + avatar.fill(Qt::transparent); + + /* + * We pick a color based on the passed character. + */ + QColor avColor = getAvatarColor(canonicalUriStr); + + /* + * We draw a circle with this color. + */ + QPainter painter(&avatar); + painter.setRenderHints(QPainter::Antialiasing | QPainter::SmoothPixmapTransform); + painter.setPen(Qt::transparent); + painter.setBrush(avColor.lighter(110)); + painter.drawEllipse(avatar.rect()); + + /* + * If a letter was passed, then we paint a letter in the circle, + * otherwise we draw the default avatar icon. + */ + QString letterStrCleaned(letterStr); + letterStrCleaned.remove(QRegExp("[\\n\\t\\r]")); + if (!letterStr.isEmpty()) { + auto unicode = letterStr.toUcs4().at(0); + if (unicode >= 0x1F000 && unicode <= 0x1FFFF) { + /* + * Is Emoticon. + */ + auto letter = QString::fromUcs4(&unicode, 1); + QFont font(QStringLiteral("Segoe UI Emoji"), avatar.height() / 2.66667, QFont::Medium); + painter.setFont(font); + QRect emojiRect(avatar.rect()); + emojiRect.moveTop(-6); + painter.drawText(emojiRect, letter, QTextOption(Qt::AlignCenter)); + } else if (unicode >= 0x0000 && unicode <= 0x00FF) { + /* + * Is Basic Latin. + */ + auto letter = letterStr.at(0).toUpper(); + QFont font("Arial", avatar.height() / 2.66667, QFont::Medium); + painter.setFont(font); + painter.setPen(Qt::white); + painter.drawText(avatar.rect(), QString(letter), QTextOption(Qt::AlignCenter)); + } else { + auto letter = QString::fromUcs4(&unicode, 1); + QFont font("Arial", avatar.height() / 2.66667, QFont::Medium); + painter.setFont(font); + painter.setPen(Qt::white); + painter.drawText(avatar.rect(), QString(letter), QTextOption(Qt::AlignCenter)); + } + } else { + QRect overlayRect = avatar.rect(); + qreal margin = (0.05 * overlayRect.width()); + overlayRect.moveLeft(overlayRect.left() + margin * 0.5); + overlayRect.moveTop(overlayRect.top() + margin * 0.5); + overlayRect.setWidth(overlayRect.width() - margin); + overlayRect.setHeight(overlayRect.height() - margin); + painter.drawPixmap(overlayRect, QPixmap(":/images/default_avatar_overlay.svg")); + } + + return avatar; +} + +QImage +Utils::fallbackAvatar(const QSize size, const std::string &alias, const std::string &uri) +{ + return fallbackAvatar(size, QString::fromStdString(uri), QString::fromStdString(alias)); +} + +QByteArray +Utils::QImageToByteArray(QImage image) +{ + QByteArray ba; + QBuffer buffer(&ba); + buffer.open(QIODevice::WriteOnly); + image.save(&buffer, "PNG"); + return ba; +} + +QImage +Utils::cropImage(const QImage &img) +{ + QRect rect; + auto w = img.width(); + auto h = img.height(); + if (w > h) { + return img.copy({(w - h) / 2, 0, h, h}); + } + return img.copy({0, (h - w) / 2, w, w}); +} + +QPixmap +Utils::pixmapFromSvg(const QString &svg_resource, const QSize &size) +{ + QSvgRenderer svgRenderer(svg_resource); + QPixmap pixmap(size); + pixmap.fill(Qt::transparent); + QPainter pixPainter(&pixmap); + svgRenderer.render(&pixPainter); + return pixmap; +} + +QImage +Utils::setupQRCode(QString ringID, int margin) +{ + auto rcode = QRcode_encodeString(ringID.toStdString().c_str(), + 0, // Let the version be decided by libqrencode + QR_ECLEVEL_L, // Lowest level of error correction + QR_MODE_8, // 8-bit data mode + 1); + if (not rcode) { + qWarning() << "Failed to generate QR code: " << strerror(errno); + return QImage(); + } + + int qrwidth = rcode->width + margin * 2; + QImage result(QSize(qrwidth, qrwidth), QImage::Format_Mono); + QPainter painter; + painter.begin(&result); + painter.setClipRect(QRect(0, 0, qrwidth, qrwidth)); + painter.setPen(QPen(Qt::black, 0.1, Qt::SolidLine, Qt::FlatCap, Qt::MiterJoin)); + painter.setBrush(Qt::black); + painter.fillRect(QRect(0, 0, qrwidth, qrwidth), Qt::white); + unsigned char *p; + p = rcode->data; + for (int y = 0; y < rcode->width; y++) { + unsigned char *row = (p + (y * rcode->width)); + for (int x = 0; x < rcode->width; x++) { + if (*(row + x) & 0x1) { + painter.drawRect(margin + x, margin + y, 1, 1); + } + } + } + painter.end(); + QRcode_free(rcode); + return result; +} + +float +Utils::getCurrentScalingRatio() +{ + return CURRENT_SCALING_RATIO; +} + +void +Utils::setCurrentScalingRatio(float ratio) +{ + CURRENT_SCALING_RATIO = ratio; +} + +QString +Utils::formattedTime(int duration) +{ + if (duration == 0) + return {}; + std::string formattedString; + auto minutes = duration / 60; + auto seconds = duration % 60; + if (minutes > 0) { + formattedString += std::to_string(minutes) + ":"; + if (formattedString.length() == 2) { + formattedString = "0" + formattedString; + } + } else { + formattedString += "00:"; + } + if (seconds < 10) + formattedString += "0"; + formattedString += std::to_string(seconds); + return QString::fromStdString(formattedString); +} + +QByteArray +Utils::QByteArrayFromFile(const QString &filename) +{ + QFile file(filename); + if (file.open(QIODevice::ReadOnly)) { + return file.readAll(); + } else { + qDebug() << "can't open file"; + return QByteArray(); + } +} + +QPixmap +Utils::generateTintedPixmap(const QString &filename, QColor color) +{ + QPixmap px(filename); + QImage tmpImage = px.toImage(); + for (int y = 0; y < tmpImage.height(); y++) { + for (int x = 0; x < tmpImage.width(); x++) { + color.setAlpha(tmpImage.pixelColor(x, y).alpha()); + tmpImage.setPixelColor(x, y, color); + } + } + return QPixmap::fromImage(tmpImage); +} + +QPixmap +Utils::generateTintedPixmap(const QPixmap &pix, QColor color) +{ + QPixmap px = pix; + QImage tmpImage = px.toImage(); + for (int y = 0; y < tmpImage.height(); y++) { + for (int x = 0; x < tmpImage.width(); x++) { + color.setAlpha(tmpImage.pixelColor(x, y).alpha()); + tmpImage.setPixelColor(x, y, color); + } + } + return QPixmap::fromImage(tmpImage); +} + +QImage +Utils::scaleAndFrame(const QImage photo, const QSize &size) +{ + return photo.scaled(size, Qt::KeepAspectRatio, Qt::SmoothTransformation); +} + +QImage +Utils::accountPhoto(const lrc::api::account::Info &accountInfo, const QSize &size) +{ + QImage photo; + if (!accountInfo.profileInfo.avatar.isEmpty()) { + QByteArray ba = accountInfo.profileInfo.avatar.toLocal8Bit(); + photo = GlobalInstances::pixmapManipulator().personPhoto(ba, nullptr).value(); + } else { + auto bestId = bestIdForAccount(accountInfo); + auto bestName = bestNameForAccount(accountInfo); + QString letterStr = bestId == bestName ? QString() : bestName; + QString prefix = accountInfo.profileInfo.type == lrc::api::profile::Type::RING ? "ring:" + : "sip:"; + photo = fallbackAvatar(size, prefix + accountInfo.profileInfo.uri, letterStr); + } + return scaleAndFrame(photo, size); +} + +QString +Utils::humanFileSize(qint64 fileSize) +{ + float fileSizeF = static_cast(fileSize); + float thresh = 1024; + + if (abs(fileSizeF) < thresh) { + return QString::number(fileSizeF) + " B"; + } + QString units[] = {"kB", "MB", "GB", "TB", "PB", "EB", "ZB", "YB"}; + int unit_position = -1; + do { + fileSizeF /= thresh; + ++unit_position; + } while (abs(fileSizeF) >= thresh && unit_position < units->size() - 1); + /* + * Round up to two decimal. + */ + fileSizeF = roundf(fileSizeF * 100) / 100; + return QString::number(fileSizeF) + " " + units[unit_position]; +} + +const QString +UtilsAdapter::getBestName(const QString &accountId, const QString &uid) +{ + auto convModel = LRCInstance::getAccountInfo(accountId).conversationModel.get(); + return Utils::bestNameForConversation(LRCInstance::getConversationFromConvUid(uid, accountId), + *convModel); +} + +const QString +UtilsAdapter::getBestId(const QString &accountId, const QString &uid) +{ + auto convModel = LRCInstance::getAccountInfo(accountId).conversationModel.get(); + return Utils::bestIdForConversation(LRCInstance::getConversationFromConvUid(uid, accountId), + *convModel); +} + +int +UtilsAdapter::getTotalUnreadMessages() +{ + int totalUnreadMessages{0}; + if (LRCInstance::getCurrentAccountInfo().profileInfo.type != lrc::api::profile::Type::SIP) { + auto convModel = LRCInstance::getCurrentConversationModel(); + auto ringConversations = convModel->getFilteredConversations(lrc::api::profile::Type::RING); + std::for_each(ringConversations.begin(), + ringConversations.end(), + [&totalUnreadMessages, convModel](const auto &conversation) { + totalUnreadMessages += conversation.unreadMessages; + }); + } + return totalUnreadMessages; +} + +int +UtilsAdapter::getTotalPendingRequest() +{ + auto &accountInfo = LRCInstance::getCurrentAccountInfo(); + return accountInfo.contactModel->pendingRequestCount(); +} + +void +UtilsAdapter::setConversationFilter(const QString &filter) +{ + LRCInstance::getCurrentConversationModel()->setFilter(filter); +} + +void +UtilsAdapter::clearConversationHistory(const QString &accountId, const QString &uid) +{ + LRCInstance::getAccountInfo(accountId).conversationModel->clearHistory(uid); +} + +void +UtilsAdapter::removeConversation(const QString &accountId, const QString &uid, bool banContact) +{ + LRCInstance::getAccountInfo(accountId).conversationModel->removeConversation(uid, banContact); +} + +const QString +UtilsAdapter::getCurrAccId() +{ + return LRCInstance::getCurrAccId(); +} + +const QStringList +UtilsAdapter::getCurrAccList() +{ + return LRCInstance::accountModel().getAccountList(); +} + +int +UtilsAdapter::getAccountListSize() +{ + return getCurrAccList().size(); +} + +void +UtilsAdapter::setCurrentCall(const QString &accountId, const QString &convUid) +{ + auto convInfo = LRCInstance::getConversationFromConvUid(convUid, accountId); + auto &accInfo = LRCInstance::getAccountInfo(accountId); + accInfo.callModel->setCurrentCall(convInfo.callId); +} + +void +UtilsAdapter::startPreviewing(bool force) +{ + LRCInstance::renderer()->startPreviewing(force); +} + +void +UtilsAdapter::stopPreviewing() +{ + if (!LRCInstance::hasVideoCall()) { + LRCInstance::renderer()->stopPreviewing(); + } +} + +bool +UtilsAdapter::hasVideoCall() +{ + return LRCInstance::hasVideoCall(); +} + +const QString +UtilsAdapter::getCallId(const QString &accountId, const QString &convUid) +{ + auto convInfo = LRCInstance::getConversationFromConvUid(convUid, accountId); + if (convInfo.uid.isEmpty()) { + return ""; + } + + auto call = LRCInstance::getCallInfoForConversation(convInfo, false); + if (!call) { + return ""; + } + + return call->id; +} + +// returns true if name is valid registered name +bool +UtilsAdapter::validateRegNameForm(const QString ®Name) +{ + QRegularExpression regExp(" "); + + if (regName.size() > 2 && !regName.contains(regExp)) { + return true; + + } else { + return false; + } +} + +QString +UtilsAdapter::getStringUTF8(QString string) +{ + return string.toUtf8(); +} + +QString +UtilsAdapter::getRecordQualityString(int value) +{ + return value ? QString::number(static_cast(value) / 100, 'f', 1) + " Mbps" : "Default"; +} + +QString +UtilsAdapter::getCurrentPath() +{ + return QDir::currentPath(); +} diff --git a/src/utils.h b/src/utils.h new file mode 100644 index 00000000..64db4517 --- /dev/null +++ b/src/utils.h @@ -0,0 +1,562 @@ +/* + * Copyright (C) 2015-2020 by Savoir-faire Linux + * Author: Edric Ladent Milaret + * Author: Andreas Traczyk + * Author: Isa Nanic + * Author: Mingrui Zhang + * + * 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 . + */ + +#pragma once + +#include "version.h" + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#ifdef Q_OS_WIN +#include +#include +#undef ERROR +#else +#define LPCWSTR char * +#endif + +#include "api/account.h" +#include "api/contact.h" +#include "api/contactmodel.h" +#include "api/conversationmodel.h" + +static const QSize IMAGE_SIZE{128, 128}; +static float CURRENT_SCALING_RATIO{1.0}; + +#ifdef BETA +static constexpr bool isBeta = true; +#else +static constexpr bool isBeta = false; +#endif + +namespace Utils { + +/* + * Qml type register. + */ +#define QML_REGISTERSINGLETONTYPE(T, MAJ, MIN) \ + qmlRegisterSingletonType("net.jami.Models", \ + MAJ, \ + MIN, \ + #T, \ + [](QQmlEngine *e, QJSEngine *se) -> QObject * { \ + Q_UNUSED(e); \ + Q_UNUSED(se); \ + T *obj = new T(); \ + return obj; \ + }); +#define QML_REGISTERSINGLETONTYPE_WITH_INSTANCE(T, MAJ, MIN) \ + qmlRegisterSingletonType("net.jami.Models", \ + MAJ, \ + MIN, \ + #T, \ + [](QQmlEngine *e, QJSEngine *se) -> QObject * { \ + Q_UNUSED(e); \ + Q_UNUSED(se); \ + return &(T::instance()); \ + }); + +#define QML_REGISTERSINGLETONTYPE_URL(URL, T, MAJ, MIN) \ + qmlRegisterSingletonType(QUrl(URL), "net.jami.Models", MAJ, MIN, #T); + +#define QML_REGISTERTYPE(T, MAJ, MIN) qmlRegisterType("net.jami.Models", MAJ, MIN, #T); + +#define QML_REGISTERNAMESPACE(T, NAME, MAJ, MIN) \ + qmlRegisterUncreatableMetaObject(T, "net.jami.Models", MAJ, MIN, NAME, "") + +#define QML_REGISTERUNCREATABLE(T, MAJ, MIN) \ + qmlRegisterUncreatableType("net.jami.Models", \ + MAJ, \ + MIN, \ + #T, \ + "Don't try to add to a qml definition of " #T); + +#define QML_REGISTERUNCREATABLE_IN_NAMESPACE(T, NAMESPACE, MAJ, MIN) \ + qmlRegisterUncreatableType("net.jami.Models", \ + MAJ, \ + MIN, \ + #T, \ + "Don't try to add to a qml definition of " #T); + +/* + * System. + */ +bool CreateStartupLink(const std::wstring &wstrAppName); +void DeleteStartupLink(const std::wstring &wstrAppName); +bool CreateLink(LPCWSTR lpszPathObj, LPCWSTR lpszPathLink); +bool CheckStartupLink(const std::wstring &wstrAppName); +void removeOldVersions(); +const char *WinGetEnv(const char *name); +QString GetRingtonePath(); +QString GenGUID(); +QString GetISODate(); +void InvokeMailto(const QString &subject, + const QString &body, + const QString &attachement = QString()); +void setStackWidget(QStackedWidget *stack, QWidget *widget); +void showSystemNotification(QWidget *widget, + const QString &message, + long delay = 5000, + const QString &triggeredAccountId = ""); +void showSystemNotification(QWidget *widget, + const QString &sender, + const QString &message, + long delay = 5000, + const QString &triggeredAccountId = ""); +QSize getRealSize(QScreen *screen); +void forceDeleteAsync(const QString &path); +QString getChangeLog(); +QString getProjectCredits(); +float getCurrentScalingRatio(); +void setCurrentScalingRatio(float ratio); + +/* + * Updates. + */ +void cleanUpdateFiles(); +void checkForUpdates(bool withUI, QWidget *parent = nullptr); +void applyUpdates(bool updateToBeta, QWidget *parent = nullptr); + +/* + * Names. + */ +QString bestIdForConversation(const lrc::api::conversation::Info &conv, + const lrc::api::ConversationModel &model); +QString bestIdForAccount(const lrc::api::account::Info &account); +QString bestNameForAccount(const lrc::api::account::Info &account); +QString bestIdForContact(const lrc::api::contact::Info &contact); +QString bestNameForContact(const lrc::api::contact::Info &contact); +QString bestNameForConversation(const lrc::api::conversation::Info &conv, + const lrc::api::ConversationModel &model); +/* + * Returns empty string if only infoHash is available. + */ +QString secondBestNameForAccount(const lrc::api::account::Info &account); +lrc::api::profile::Type profileType(const lrc::api::conversation::Info &conv, + const lrc::api::ConversationModel &model); + +/* + * Interactions. + */ +std::string formatTimeString(const std::time_t ×tamp); +bool isInteractionGenerated(const lrc::api::interaction::Type &interaction); +bool isContactValid(const QString &contactUid, const lrc::api::ConversationModel &model); +bool getReplyMessageBox(QWidget *widget, const QString &title, const QString &text); + +/* + * Image. + */ +QString getContactImageString(const QString &accountId, const QString &uid); +QImage getCirclePhoto(const QImage original, int sizePhoto); +QImage conversationPhoto(const QString &convUid, + const lrc::api::account::Info &accountInfo, + bool filtered = false); +QColor getAvatarColor(const QString &canonicalUri); +QImage fallbackAvatar(const QSize size, + const QString &canonicalUriStr, + const QString &letterStr = QString()); +QImage fallbackAvatar(const QSize size, const std::string &alias, const std::string &uri); +QByteArray QImageToByteArray(QImage image); +QByteArray QByteArrayFromFile(const QString &filename); +QPixmap generateTintedPixmap(const QString &filename, QColor color); +QPixmap generateTintedPixmap(const QPixmap &pix, QColor color); +QImage scaleAndFrame(const QImage photo, const QSize &size = IMAGE_SIZE); +QImage accountPhoto(const lrc::api::account::Info &accountInfo, const QSize &size = IMAGE_SIZE); +QImage cropImage(const QImage &img); +QPixmap pixmapFromSvg(const QString &svg_resource, const QSize &size); +QImage setupQRCode(QString ringID, int margin); + +/* + * Rounded corner. + */ +template +void +fillRoundRectPath(QPainter &painter, + const T &brushType, + const QRect &rectToDraw, + qreal cornerRadius, + int xTransFormOffset = 0, + int yTransFormOffset = 0) +{ + QBrush brush(brushType); + brush.setTransform(QTransform::fromTranslate(rectToDraw.x() + xTransFormOffset, + rectToDraw.y() + yTransFormOffset)); + QPainterPath painterPath; + painterPath.addRoundRect(rectToDraw, cornerRadius); + painter.fillPath(painterPath, brush); +} + +/* + * Time. + */ +QString formattedTime(int seconds); + +/* + * Byte to human readable size. + */ +QString humanFileSize(qint64 fileSize); + +/* + * Device plug or unplug enum. + */ +enum class DevicePlugStatus { Plugged, Unplugged, Unchanged }; + +class OneShotDisconnectConnection : public QObject +{ + Q_OBJECT + +public: + explicit OneShotDisconnectConnection(const QObject *sender, + const char *signal, + QMetaObject::Connection *connection, + QObject *parent = nullptr) + : QObject(parent) + { + connection_ = connection; + disconnectConnection_ = new QMetaObject::Connection; + *disconnectConnection_ = QObject::connect(sender, + signal, + this, + SLOT(slotOneShotDisconnectConnection())); + } + ~OneShotDisconnectConnection() + { + if (!connection_) { + delete connection_; + } + if (!disconnectConnection_) { + delete disconnectConnection_; + } + if (!this) { + delete this; + } + } + +public slots: + void + slotOneShotDisconnectConnection() + { + if (connection_) { + QObject::disconnect(*connection_); + delete connection_; + } + if (disconnectConnection_) { + QObject::disconnect(*disconnectConnection_); + delete disconnectConnection_; + } + delete this; + } + +private: + QMetaObject::Connection *connection_; + QMetaObject::Connection *disconnectConnection_; +}; + +template +void +oneShotConnect(const typename QtPrivate::FunctionPointer::Object *sender, + Func1 signal, + Func2 slot) +{ + QMetaObject::Connection *const connection = new QMetaObject::Connection; + *connection = QObject::connect(sender, signal, slot); + QMetaObject::Connection *const disconnectConnection = new QMetaObject::Connection; + *disconnectConnection = QObject::connect(sender, signal, [connection, disconnectConnection] { + if (connection) { + QObject::disconnect(*connection); + delete connection; + } + if (disconnectConnection) { + QObject::disconnect(*disconnectConnection); + delete disconnectConnection; + } + }); +} + +template +void +oneShotConnect(const typename QtPrivate::FunctionPointer::Object *sender, + Func1 signal, + const typename QtPrivate::FunctionPointer::Object *receiver, + Func2 slot) +{ + QMetaObject::Connection *const connection = new QMetaObject::Connection; + *connection = QObject::connect(sender, signal, receiver, slot); + QMetaObject::Connection *const disconnectConnection = new QMetaObject::Connection; + *disconnectConnection = QObject::connect(sender, signal, [connection, disconnectConnection] { + if (connection) { + QObject::disconnect(*connection); + delete connection; + } + if (disconnectConnection) { + QObject::disconnect(*disconnectConnection); + delete disconnectConnection; + } + }); +} + +inline void +oneShotConnect(const QObject *sender, const char *signal, const QObject *receiver, const char *slot) +{ + QMetaObject::Connection *const connection = new QMetaObject::Connection; + *connection = QObject::connect(sender, signal, receiver, slot); + OneShotDisconnectConnection *disconnectConnection = new OneShotDisconnectConnection(sender, + signal, + connection); + Q_UNUSED(disconnectConnection) +} + +template +class Blocker +{ + T *blocked; + bool previous; + +public: + Blocker(T *blocked) + : blocked(blocked) + , previous(blocked->blockSignals(true)) + {} + ~Blocker() { blocked->blockSignals(previous); } + T * + operator->() + { + return blocked; + } +}; + +template +inline Blocker +whileBlocking(T *blocked) +{ + return Blocker(blocked); +} + +template +void +setElidedText(T *object, + const QString &text, + Qt::TextElideMode mode = Qt::ElideMiddle, + int padding = 32) +{ + QFontMetrics metrics(object->font()); + QString clippedText = metrics.elidedText(text, mode, object->width() - padding); + object->setText(clippedText); +} + +template +constexpr inline + typename std::enable_if::value, typename std::underlying_type::type>::type + toUnderlyingValue(E e) noexcept +{ + return static_cast::type>(e); +} + +template +constexpr inline + typename std::enable_if::value && std::is_integral::value, E>::type + toEnum(T value) noexcept +{ + return static_cast(value); +} +} // namespace Utils + +class UtilsAdapter : public QObject +{ + Q_OBJECT +public: + explicit UtilsAdapter(QObject *parent = nullptr) + : QObject(parent) + { + clipboard_ = QApplication::clipboard(); + } + ~UtilsAdapter() {} + + ///Singleton + static UtilsAdapter &instance(); + + Q_INVOKABLE const QString + getChangeLog() + { + return Utils::getChangeLog(); + } + + Q_INVOKABLE const QString + getProjectCredits() + { + return Utils::getProjectCredits(); + } + + Q_INVOKABLE const QString + getVersionStr() + { + return QString(VERSION_STRING); + } + + Q_INVOKABLE void + setText(QString text) + { + clipboard_->setText(text, QClipboard::Clipboard); + } + + Q_INVOKABLE const QString + qStringFromFile(const QString &filename) + { + return Utils::QByteArrayFromFile(filename); + } + + Q_INVOKABLE const QString + getStyleSheet(const QString &name, const QString &source) + { + auto simplifiedCSS = source.simplified().replace("'", "\""); + QString s = QString::fromLatin1("(function() {" + " var node = document.createElement('style');" + " node.id = '%1';" + " node.innerHTML = '%2';" + " document.head.appendChild(node);" + "})()") + .arg(name) + .arg(simplifiedCSS); + return s; + } + + Q_INVOKABLE const QString + getCachePath() + { + QDir dataDir(QStandardPaths::writableLocation(QStandardPaths::AppLocalDataLocation)); + dataDir.cdUp(); + return dataDir.absolutePath() + "/jami"; + } + Q_INVOKABLE bool + createStartupLink() + { + return Utils::CreateStartupLink(L"Jami"); + } + Q_INVOKABLE QString + GetRingtonePath() + { + return Utils::GetRingtonePath(); + } + Q_INVOKABLE bool + checkStartupLink() + { + return Utils::CheckStartupLink(L"Jami"); + } + + Q_INVOKABLE const QString + getContactImageString(const QString &accountId, const QString &uid) + { + return Utils::getContactImageString(accountId, uid); + } + + Q_INVOKABLE void removeConversation(const QString &accountId, + const QString &uid, + bool banContact = false); + Q_INVOKABLE void clearConversationHistory(const QString &accountId, const QString &uid); + Q_INVOKABLE void setConversationFilter(const QString &filter); + Q_INVOKABLE int getTotalUnreadMessages(); + Q_INVOKABLE int getTotalPendingRequest(); + Q_INVOKABLE const QString getBestName(const QString &accountId, const QString &uid); + Q_INVOKABLE const QString getBestId(const QString &accountId, const QString &uid); + + Q_INVOKABLE const QString getCurrAccId(); + Q_INVOKABLE const QStringList getCurrAccList(); + Q_INVOKABLE int getAccountListSize(); + Q_INVOKABLE void setCurrentCall(const QString &accountId, const QString &convUid); + Q_INVOKABLE void startPreviewing(bool force); + Q_INVOKABLE void stopPreviewing(); + Q_INVOKABLE bool hasVideoCall(); + Q_INVOKABLE const QString getCallId(const QString &accountId, const QString &convUid); + Q_INVOKABLE QString getStringUTF8(QString string); + Q_INVOKABLE bool validateRegNameForm(const QString ®Name); + Q_INVOKABLE QString getRecordQualityString(int value); + Q_INVOKABLE QString getCurrentPath(); + Q_INVOKABLE QString + stringSimplifier(QString input) + { + return input.simplified(); + } + + Q_INVOKABLE QString + toNativeSeparators(QString inputDir) + { + return QDir::toNativeSeparators(inputDir); + } + + Q_INVOKABLE QString + toFileInfoName(QString inputFileName) + { + QFileInfo fi(inputFileName); + return fi.fileName(); + } + + Q_INVOKABLE QString + toFileAbsolutepath(QString inputFileName) + { + QFileInfo fi(inputFileName); + return fi.absolutePath(); + } + + Q_INVOKABLE QString + getAbsPath(QString path) + { +#ifdef Q_OS_WIN + return path.replace("file:///", "").replace("\n", "").replace("\r", ""); +#else + return path.replace("file:///", "/").replace("\n", "").replace("\r", ""); +#endif + } + + Q_INVOKABLE QString + getCroppedImageBase64FromFile(QString fileName, int size) + { + auto image = Utils::cropImage(QImage(fileName)); + auto croppedImage = image.scaled(size, + size, + Qt::KeepAspectRatioByExpanding, + Qt::SmoothTransformation); + return QString::fromLatin1(Utils::QImageToByteArray(croppedImage).toBase64().data()); + } + +private: + QClipboard *clipboard_; +}; +#if QT_VERSION >= QT_VERSION_CHECK(5, 8, 0) +Q_DECLARE_METATYPE(UtilsAdapter *) +#endif diff --git a/src/version.h b/src/version.h new file mode 100644 index 00000000..d5eea6dc --- /dev/null +++ b/src/version.h @@ -0,0 +1,57 @@ +#pragma once + +#define BUILD_YEAR_CH0 (__DATE__[ 7]) +#define BUILD_YEAR_CH1 (__DATE__[ 8]) +#define BUILD_YEAR_CH2 (__DATE__[ 9]) +#define BUILD_YEAR_CH3 (__DATE__[10]) + +#define BUILD_MONTH_IS_JAN (__DATE__[0] == 'J' && __DATE__[1] == 'a' && __DATE__[2] == 'n') +#define BUILD_MONTH_IS_FEB (__DATE__[0] == 'F') +#define BUILD_MONTH_IS_MAR (__DATE__[0] == 'M' && __DATE__[1] == 'a' && __DATE__[2] == 'r') +#define BUILD_MONTH_IS_APR (__DATE__[0] == 'A' && __DATE__[1] == 'p') +#define BUILD_MONTH_IS_MAY (__DATE__[0] == 'M' && __DATE__[1] == 'a' && __DATE__[2] == 'y') +#define BUILD_MONTH_IS_JUN (__DATE__[0] == 'J' && __DATE__[1] == 'u' && __DATE__[2] == 'n') +#define BUILD_MONTH_IS_JUL (__DATE__[0] == 'J' && __DATE__[1] == 'u' && __DATE__[2] == 'l') +#define BUILD_MONTH_IS_AUG (__DATE__[0] == 'A' && __DATE__[1] == 'u') +#define BUILD_MONTH_IS_SEP (__DATE__[0] == 'S') +#define BUILD_MONTH_IS_OCT (__DATE__[0] == 'O') +#define BUILD_MONTH_IS_NOV (__DATE__[0] == 'N') +#define BUILD_MONTH_IS_DEC (__DATE__[0] == 'D') + +#define BUILD_MONTH_CH0 \ + ((BUILD_MONTH_IS_OCT || BUILD_MONTH_IS_NOV || BUILD_MONTH_IS_DEC) ? '1' : '0') + +#define BUILD_MONTH_CH1 \ + ( \ + (BUILD_MONTH_IS_JAN) ? '1' : \ + (BUILD_MONTH_IS_FEB) ? '2' : \ + (BUILD_MONTH_IS_MAR) ? '3' : \ + (BUILD_MONTH_IS_APR) ? '4' : \ + (BUILD_MONTH_IS_MAY) ? '5' : \ + (BUILD_MONTH_IS_JUN) ? '6' : \ + (BUILD_MONTH_IS_JUL) ? '7' : \ + (BUILD_MONTH_IS_AUG) ? '8' : \ + (BUILD_MONTH_IS_SEP) ? '9' : \ + (BUILD_MONTH_IS_OCT) ? '0' : \ + (BUILD_MONTH_IS_NOV) ? '1' : \ + (BUILD_MONTH_IS_DEC) ? '2' : \ + /* error default */ '?' \ + ) + +#define BUILD_DAY_CH0 ((__DATE__[4] >= '0') ? (__DATE__[4]) : '0') +#define BUILD_DAY_CH1 (__DATE__[ 5]) + +#define BUILD_HOUR_CH0 (__TIME__[0]) +#define BUILD_HOUR_CH1 (__TIME__[1]) + +#define BUILD_MIN_CH0 (__TIME__[ 3]) +#define BUILD_MIN_CH1 (__TIME__[ 4]) + +const char VERSION_STRING[] = { + BUILD_YEAR_CH0, BUILD_YEAR_CH1, BUILD_YEAR_CH2, BUILD_YEAR_CH3, + BUILD_MONTH_CH0, BUILD_MONTH_CH1, + BUILD_DAY_CH0, BUILD_DAY_CH1, + BUILD_HOUR_CH0, BUILD_HOUR_CH1, + BUILD_MIN_CH0, BUILD_MIN_CH1, + '\0' +}; \ No newline at end of file diff --git a/src/videocodeclistmodel.cpp b/src/videocodeclistmodel.cpp new file mode 100644 index 00000000..d77a207c --- /dev/null +++ b/src/videocodeclistmodel.cpp @@ -0,0 +1,130 @@ +/* + * Copyright (C) 2019-2020 by Savoir-faire Linux + * Author: Yang Wang + * + * 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 . + */ + +#include "videocodeclistmodel.h" + +#include + +VideoCodecListModel::VideoCodecListModel(QObject *parent) + : QAbstractListModel(parent) +{} + +VideoCodecListModel::~VideoCodecListModel() {} + +int +VideoCodecListModel::rowCount(const QModelIndex &parent) const +{ + if (!parent.isValid()) { + /* + * Count. + */ + QList realCodecList; + auto videoCodecListOld = LRCInstance::getCurrentAccountInfo().codecModel->getVideoCodecs(); + + for (auto codec : videoCodecListOld) { + if (codec.name.length()) { + realCodecList.append(codec); + } + } + + return realCodecList.size(); + } + /* + * A valid QModelIndex returns 0 as no entry has sub-elements. + */ + return 0; +} + +int +VideoCodecListModel::columnCount(const QModelIndex &parent) const +{ + Q_UNUSED(parent); + /* + * Only need one column. + */ + return 1; +} + +QVariant +VideoCodecListModel::data(const QModelIndex &index, int role) const +{ + auto videoCodecList = LRCInstance::getCurrentAccountInfo().codecModel->getVideoCodecs(); + if (!index.isValid() || videoCodecList.size() <= index.row()) { + return QVariant(); + } + + QList realCodecList; + + for (auto codec : videoCodecList) { + if (codec.name.length()) { + realCodecList.append(codec); + } + } + + switch (role) { + case Role::VideoCodecName: + return QVariant(realCodecList.at(index.row()).name); + case Role::IsEnabled: + return QVariant(realCodecList.at(index.row()).enabled); + case Role::VideoCodecID: + return QVariant(realCodecList.at(index.row()).id); + } + return QVariant(); +} + +QHash +VideoCodecListModel::roleNames() const +{ + QHash roles; + roles[VideoCodecName] = "VideoCodecName"; + roles[IsEnabled] = "IsEnabled"; + roles[VideoCodecID] = "VideoCodecID"; + return roles; +} + +QModelIndex +VideoCodecListModel::index(int row, int column, const QModelIndex &parent) const +{ + Q_UNUSED(parent); + if (column != 0) { + return QModelIndex(); + } + + if (row >= 0 && row < rowCount()) { + return createIndex(row, column); + } + return QModelIndex(); +} + +QModelIndex +VideoCodecListModel::parent(const QModelIndex &child) const +{ + Q_UNUSED(child); + return QModelIndex(); +} + +Qt::ItemFlags +VideoCodecListModel::flags(const QModelIndex &index) const +{ + auto flags = QAbstractItemModel::flags(index) | Qt::ItemNeverHasChildren | Qt::ItemIsSelectable + | Qt::ItemIsUserCheckable | Qt::ItemIsEnabled; + if (!index.isValid()) { + return QAbstractItemModel::flags(index); + } + return flags; +} diff --git a/src/videocodeclistmodel.h b/src/videocodeclistmodel.h new file mode 100644 index 00000000..96a34a71 --- /dev/null +++ b/src/videocodeclistmodel.h @@ -0,0 +1,53 @@ +/* + * Copyright (C) 2019-2020 by Savoir-faire Linux + * Author: Yang Wang + * + * 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 . + */ + +#pragma once + +#include + +#include "api/account.h" +#include "api/contact.h" +#include "api/conversation.h" +#include "api/newdevicemodel.h" + +#include "lrcinstance.h" + +class VideoCodecListModel : public QAbstractListModel +{ + Q_OBJECT +public: + enum Role { VideoCodecName = Qt::UserRole + 1, IsEnabled, VideoCodecID }; + Q_ENUM(Role) + + explicit VideoCodecListModel(QObject *parent = 0); + ~VideoCodecListModel(); + + /* + * QAbstractListModel override. + */ + int rowCount(const QModelIndex &parent = QModelIndex()) const override; + int columnCount(const QModelIndex &parent) const override; + QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override; + /* + * Override role name as access point in qml. + */ + QHash roleNames() const override; + QModelIndex index(int row, int column = 0, const QModelIndex &parent = QModelIndex()) const; + QModelIndex parent(const QModelIndex &child) const; + Qt::ItemFlags flags(const QModelIndex &index) const; +}; diff --git a/src/videoformatfpsmodel.cpp b/src/videoformatfpsmodel.cpp new file mode 100644 index 00000000..4c5fe15e --- /dev/null +++ b/src/videoformatfpsmodel.cpp @@ -0,0 +1,216 @@ +/* + * Copyright (C) 2019-2020 by Savoir-faire Linux + * Author: Yang Wang + * + * 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 . + */ + +#include "videoformatfpsmodel.h" + +VideoFormatFpsModel::VideoFormatFpsModel(QObject *parent) + : QAbstractListModel(parent) +{ + try { + QString currentDeviceId = LRCInstance::avModel().getCurrentVideoCaptureDevice(); + auto currentSettings = LRCInstance::avModel().getDeviceSettings(currentDeviceId); + currentResolution_ = currentSettings.size; + } catch (const std::exception &e) { + qWarning() << "Constructor of VideoFormatFpsModel, exception: " << e.what(); + } +} + +VideoFormatFpsModel::~VideoFormatFpsModel() {} + +int +VideoFormatFpsModel::rowCount(const QModelIndex &parent) const +{ + if (!parent.isValid()) { + /* + * Count. + */ + QString currentDeviceId = LRCInstance::avModel().getCurrentVideoCaptureDevice(); + auto deviceCapabilities = LRCInstance::avModel().getDeviceCapabilities(currentDeviceId); + if (deviceCapabilities.size() == 0) { + return 0; + } + try { + auto currentSettings = LRCInstance::avModel().getDeviceSettings(currentDeviceId); + auto currentChannel = currentSettings.channel; + currentChannel = currentChannel.isEmpty() ? "default" : currentChannel; + auto channelCaps = deviceCapabilities[currentChannel]; + + bool resolutionFound = false; + int indexOfCurrentResolutionInResRateList = 0; + + for (int i = 0; i < channelCaps.size(); i++) { + if (channelCaps[i].first == currentResolution_) { + indexOfCurrentResolutionInResRateList = i; + resolutionFound = true; + break; + } + } + + if (resolutionFound) { + auto fpsList = channelCaps[indexOfCurrentResolutionInResRateList].second; + return fpsList.size(); + } + } catch (const std::exception &e) { + qWarning() << e.what(); + } + return 0; + } + /* + * A valid QModelIndex returns 0 as no entry has sub-elements. + */ + return 0; +} + +int +VideoFormatFpsModel::columnCount(const QModelIndex &parent) const +{ + Q_UNUSED(parent); + /* + * Only need one column. + */ + return 1; +} + +QVariant +VideoFormatFpsModel::data(const QModelIndex &index, int role) const +{ + try { + QString currentDeviceId = LRCInstance::avModel().getCurrentVideoCaptureDevice(); + auto deviceCapabilities = LRCInstance::avModel().getDeviceCapabilities(currentDeviceId); + + auto currentSettings = LRCInstance::avModel().getDeviceSettings(currentDeviceId); + auto currentChannel = currentSettings.channel; + currentChannel = currentChannel.isEmpty() ? "default" : currentChannel; + auto channelCaps = deviceCapabilities[currentChannel]; + + bool resolutionFound = false; + int indexOfCurrentResolutionInResRateList = 0; + + for (int i = 0; i < channelCaps.size(); i++) { + if (channelCaps[i].first == currentResolution_) { + indexOfCurrentResolutionInResRateList = i; + resolutionFound = true; + break; + } + } + + if (!index.isValid() || channelCaps.size() <= index.row() || deviceCapabilities.size() == 0 + || !resolutionFound) { + return QVariant(); + } + + auto fpsList = channelCaps[indexOfCurrentResolutionInResRateList].second; + + switch (role) { + case Role::FPS: + return QVariant(fpsList[index.row()]); + case Role::FPS_ToDisplay_UTF8: + QString rateDisplayUtf8 = QString("%1 fps").arg((int) fpsList[index.row()]); + return QVariant(rateDisplayUtf8.toUtf8()); + } + + } catch (const std::exception &e) { + qWarning() << e.what(); + } + + return QVariant(); +} + +QHash +VideoFormatFpsModel::roleNames() const +{ + QHash roles; + roles[FPS] = "FPS"; + roles[FPS_ToDisplay_UTF8] = "FPS_ToDisplay_UTF8"; + return roles; +} + +QModelIndex +VideoFormatFpsModel::index(int row, int column, const QModelIndex &parent) const +{ + Q_UNUSED(parent); + if (column != 0) { + return QModelIndex(); + } + + if (row >= 0 && row < rowCount()) { + return createIndex(row, column); + } + return QModelIndex(); +} + +QModelIndex +VideoFormatFpsModel::parent(const QModelIndex &child) const +{ + Q_UNUSED(child); + return QModelIndex(); +} + +Qt::ItemFlags +VideoFormatFpsModel::flags(const QModelIndex &index) const +{ + auto flags = QAbstractItemModel::flags(index) | Qt::ItemNeverHasChildren | Qt::ItemIsSelectable; + if (!index.isValid()) { + return QAbstractItemModel::flags(index); + } + return flags; +} + +void +VideoFormatFpsModel::reset() +{ + beginResetModel(); + endResetModel(); +} + +int +VideoFormatFpsModel::getCurrentSettingIndex() +{ + int resultRowIndex = 0; + try { + QString currentDeviceId = LRCInstance::avModel().getCurrentVideoCaptureDevice(); + auto currentSettings = LRCInstance::avModel().getDeviceSettings(currentDeviceId); + float currentFps = currentSettings.rate; + auto resultList = match(index(0, 0), FPS, QVariant(currentFps)); + + if (resultList.size() > 0) { + resultRowIndex = resultList[0].row(); + } + + } catch (const std::exception &e) { + qWarning() << e.what(); + } + + return resultRowIndex; +} + +QString +VideoFormatFpsModel::getCurrentResolution() +{ + return currentResolution_; +} + +void +VideoFormatFpsModel::setCurrentResolution(QString resNew) +{ + if (currentResolution_ != resNew) { + currentResolution_ = resNew; + reset(); + emit currentResolutionChanged(resNew); + } +} diff --git a/src/videoformatfpsmodel.h b/src/videoformatfpsmodel.h new file mode 100644 index 00000000..cd165ccf --- /dev/null +++ b/src/videoformatfpsmodel.h @@ -0,0 +1,77 @@ +/* + * Copyright (C) 2019-2020 by Savoir-faire Linux + * Author: Yang Wang + * + * 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 . + */ + +#pragma once + +#include + +#include "api/account.h" +#include "api/contact.h" +#include "api/conversation.h" +#include "api/newdevicemodel.h" + +#include "lrcinstance.h" + +class VideoFormatFpsModel : public QAbstractListModel +{ + Q_OBJECT + Q_PROPERTY(QString currentResolution READ getCurrentResolution WRITE setCurrentResolution NOTIFY + currentResolutionChanged); + +public: + enum Role { FPS = Qt::UserRole + 1, FPS_ToDisplay_UTF8 }; + Q_ENUM(Role) + + explicit VideoFormatFpsModel(QObject *parent = 0); + ~VideoFormatFpsModel(); + + /* + * QAbstractListModel override. + */ + int rowCount(const QModelIndex &parent = QModelIndex()) const override; + int columnCount(const QModelIndex &parent) const override; + QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override; + /* + * Override role name as access point in qml. + */ + QHash roleNames() const override; + QModelIndex index(int row, int column = 0, const QModelIndex &parent = QModelIndex()) const; + QModelIndex parent(const QModelIndex &child) const; + Qt::ItemFlags flags(const QModelIndex &index) const; + + /* + * This function is to reset the model when there's new account added. + */ + Q_INVOKABLE void reset(); + /* + * This function is to get the current device id in the demon. + */ + Q_INVOKABLE int getCurrentSettingIndex(); + + /* + * Getters and setters + */ + QString getCurrentResolution(); + void setCurrentResolution(QString resNew); + +signals: + void currentResolutionChanged(QString resNew); + +private: + QString currentResolution_; +}; diff --git a/src/videoformatresolutionmodel.cpp b/src/videoformatresolutionmodel.cpp new file mode 100644 index 00000000..dea96358 --- /dev/null +++ b/src/videoformatresolutionmodel.cpp @@ -0,0 +1,164 @@ +/* + * Copyright (C) 2019-2020 by Savoir-faire Linux + * Author: Yang Wang + * + * 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 . + */ + +#include "videoformatresolutionmodel.h" + +VideoFormatResolutionModel::VideoFormatResolutionModel(QObject *parent) + : QAbstractListModel(parent) +{} + +VideoFormatResolutionModel::~VideoFormatResolutionModel() {} + +int +VideoFormatResolutionModel::rowCount(const QModelIndex &parent) const +{ + if (!parent.isValid()) { + /* + * Count. + */ + QString currentDeviceId = LRCInstance::avModel().getCurrentVideoCaptureDevice(); + auto deviceCapabilities = LRCInstance::avModel().getDeviceCapabilities(currentDeviceId); + if (deviceCapabilities.size() == 0) { + return 0; + } + try { + auto currentSettings = LRCInstance::avModel().getDeviceSettings(currentDeviceId); + auto currentChannel = currentSettings.channel; + currentChannel = currentChannel.isEmpty() ? "default" : currentChannel; + auto channelCaps = deviceCapabilities[currentChannel]; + + return channelCaps.size(); + } catch (const std::exception &e) { + qWarning() << e.what(); + return 0; + } + } + /* + * A valid QModelIndex returns 0 as no entry has sub-elements. + */ + return 0; +} + +int +VideoFormatResolutionModel::columnCount(const QModelIndex &parent) const +{ + Q_UNUSED(parent); + /* + * Only need one column. + */ + return 1; +} + +QVariant +VideoFormatResolutionModel::data(const QModelIndex &index, int role) const +{ + try { + QString currentDeviceId = LRCInstance::avModel().getCurrentVideoCaptureDevice(); + auto deviceCapabilities = LRCInstance::avModel().getDeviceCapabilities(currentDeviceId); + + auto currentSettings = LRCInstance::avModel().getDeviceSettings(currentDeviceId); + auto currentChannel = currentSettings.channel; + currentChannel = currentChannel.isEmpty() ? "default" : currentChannel; + auto channelCaps = deviceCapabilities[currentChannel]; + + if (!index.isValid() || channelCaps.size() <= index.row() + || deviceCapabilities.size() == 0) { + return QVariant(); + } + + switch (role) { + case Role::Resolution: + return QVariant(channelCaps.at(index.row()).first); + case Role::Resolution_UTF8: + return QVariant(channelCaps.at(index.row()).first.toUtf8()); + } + + } catch (const std::exception &e) { + qWarning() << e.what(); + } + + return QVariant(); +} + +QHash +VideoFormatResolutionModel::roleNames() const +{ + QHash roles; + roles[Resolution] = "Resolution"; + roles[Resolution_UTF8] = "Resolution_UTF8"; + return roles; +} + +QModelIndex +VideoFormatResolutionModel::index(int row, int column, const QModelIndex &parent) const +{ + Q_UNUSED(parent); + if (column != 0) { + return QModelIndex(); + } + + if (row >= 0 && row < rowCount()) { + return createIndex(row, column); + } + return QModelIndex(); +} + +QModelIndex +VideoFormatResolutionModel::parent(const QModelIndex &child) const +{ + Q_UNUSED(child); + return QModelIndex(); +} + +Qt::ItemFlags +VideoFormatResolutionModel::flags(const QModelIndex &index) const +{ + auto flags = QAbstractItemModel::flags(index) | Qt::ItemNeverHasChildren | Qt::ItemIsSelectable; + if (!index.isValid()) { + return QAbstractItemModel::flags(index); + } + return flags; +} + +void +VideoFormatResolutionModel::reset() +{ + beginResetModel(); + endResetModel(); +} + +int +VideoFormatResolutionModel::getCurrentSettingIndex() +{ + int resultRowIndex = 0; + try { + QString currentDeviceId = LRCInstance::avModel().getCurrentVideoCaptureDevice(); + auto currentSettings = LRCInstance::avModel().getDeviceSettings(currentDeviceId); + QString currentResolution = currentSettings.size; + auto resultList = match(index(0, 0), Resolution, QVariant(currentResolution)); + + if (resultList.size() > 0) { + resultRowIndex = resultList[0].row(); + } + + } catch (const std::exception &e) { + qWarning() << e.what(); + } + + return resultRowIndex; +} diff --git a/src/videoformatresolutionmodel.h b/src/videoformatresolutionmodel.h new file mode 100644 index 00000000..8a3c8032 --- /dev/null +++ b/src/videoformatresolutionmodel.h @@ -0,0 +1,62 @@ +/* + * Copyright (C) 2019-2020 by Savoir-faire Linux + * Author: Yang Wang + * + * 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 . + */ + +#pragma once + +#include + +#include "api/account.h" +#include "api/contact.h" +#include "api/conversation.h" +#include "api/newdevicemodel.h" + +#include "lrcinstance.h" + +class VideoFormatResolutionModel : public QAbstractListModel +{ + Q_OBJECT +public: + enum Role { Resolution = Qt::UserRole + 1, Resolution_UTF8 }; + Q_ENUM(Role) + + explicit VideoFormatResolutionModel(QObject *parent = 0); + ~VideoFormatResolutionModel(); + + /* + * QAbstractListModel override. + */ + int rowCount(const QModelIndex &parent = QModelIndex()) const override; + int columnCount(const QModelIndex &parent) const override; + QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override; + /* + * Override role name as access point in qml. + */ + QHash roleNames() const override; + QModelIndex index(int row, int column = 0, const QModelIndex &parent = QModelIndex()) const; + QModelIndex parent(const QModelIndex &child) const; + Qt::ItemFlags flags(const QModelIndex &index) const; + + /* + * This function is to reset the model when there's new account added. + */ + Q_INVOKABLE void reset(); + /* + * This function is to get the current device id in the demon. + */ + Q_INVOKABLE int getCurrentSettingIndex(); +}; diff --git a/src/videoinputdevicemodel.cpp b/src/videoinputdevicemodel.cpp new file mode 100644 index 00000000..dfc349b3 --- /dev/null +++ b/src/videoinputdevicemodel.cpp @@ -0,0 +1,166 @@ +/* + * Copyright (C) 2019-2020 by Savoir-faire Linux + * Author: Yang Wang + * + * 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 . + */ + +#include "videoinputdevicemodel.h" + +VideoInputDeviceModel::VideoInputDeviceModel(QObject *parent) + : QAbstractListModel(parent) +{} + +VideoInputDeviceModel::~VideoInputDeviceModel() {} + +int +VideoInputDeviceModel::rowCount(const QModelIndex &parent) const +{ + if (!parent.isValid()) { + /* + * Count. + */ + int deviceListSize = LRCInstance::avModel().getDevices().size(); + if (deviceListSize > 0) { + return deviceListSize; + } else { + return 1; + } + } + /* + * A valid QModelIndex returns 0 as no entry has sub-elements. + */ + return 0; +} + +int +VideoInputDeviceModel::columnCount(const QModelIndex &parent) const +{ + Q_UNUSED(parent); + /* + * Only need one column. + */ + return 1; +} + +QVariant +VideoInputDeviceModel::data(const QModelIndex &index, int role) const +{ + auto deviceList = LRCInstance::avModel().getDevices(); + if (!index.isValid()) { + return QVariant(); + } + + if (deviceList.size() == 0 && index.row() == 0) { + switch (role) { + case Role::DeviceName: + return QVariant(QObject::tr("No Device")); + case Role::DeviceName_UTF8: + return QVariant(QObject::tr("No Device").toUtf8()); + } + } + + if (deviceList.size() <= index.row()) { + return QVariant(); + } + + auto currentDeviceSetting = LRCInstance::avModel().getDeviceSettings(deviceList[index.row()]); + + switch (role) { + case Role::DeviceChannel: + return QVariant((QString) currentDeviceSetting.channel); + case Role::DeviceName: + return QVariant(currentDeviceSetting.name); + case Role::DeviceId: + return QVariant(currentDeviceSetting.id); + case Role::CurrentFrameRate: + return QVariant((float) currentDeviceSetting.rate); + case Role::CurrentResolution: + return QVariant((QString) currentDeviceSetting.size); + case Role::DeviceName_UTF8: + return QVariant(currentDeviceSetting.name.toUtf8()); + } + return QVariant(); +} + +QHash +VideoInputDeviceModel::roleNames() const +{ + QHash roles; + roles[DeviceChannel] = "DeviceChannel"; + roles[DeviceName] = "DeviceName"; + roles[DeviceId] = "DeviceId"; + roles[CurrentFrameRate] = "CurrentFrameRate"; + roles[CurrentResolution] = "CurrentResolution"; + roles[DeviceName_UTF8] = "DeviceName_UTF8"; + return roles; +} + +QModelIndex +VideoInputDeviceModel::index(int row, int column, const QModelIndex &parent) const +{ + Q_UNUSED(parent); + if (column != 0) { + return QModelIndex(); + } + + if (row >= 0 && row < rowCount()) { + return createIndex(row, column); + } + return QModelIndex(); +} + +QModelIndex +VideoInputDeviceModel::parent(const QModelIndex &child) const +{ + Q_UNUSED(child); + return QModelIndex(); +} + +Qt::ItemFlags +VideoInputDeviceModel::flags(const QModelIndex &index) const +{ + auto flags = QAbstractItemModel::flags(index) | Qt::ItemNeverHasChildren | Qt::ItemIsSelectable; + if (!index.isValid()) { + return QAbstractItemModel::flags(index); + } + return flags; +} + +void +VideoInputDeviceModel::reset() +{ + beginResetModel(); + endResetModel(); +} + +int +VideoInputDeviceModel::deviceCount() +{ + return LRCInstance::avModel().getDevices().size(); +} + +int +VideoInputDeviceModel::getCurrentSettingIndex() +{ + QString currentId = LRCInstance::avModel().getCurrentVideoCaptureDevice(); + auto resultList = match(index(0, 0), DeviceId, QVariant(currentId)); + + int resultRowIndex = 0; + if (resultList.size() > 0) { + resultRowIndex = resultList[0].row(); + } + + return resultRowIndex; +} diff --git a/src/videoinputdevicemodel.h b/src/videoinputdevicemodel.h new file mode 100644 index 00000000..99d5898e --- /dev/null +++ b/src/videoinputdevicemodel.h @@ -0,0 +1,73 @@ +/* + * Copyright (C) 2019-2020 by Savoir-faire Linux + * Author: Yang Wang + * + * 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 . + */ + +#pragma once + +#include + +#include "api/account.h" +#include "api/contact.h" +#include "api/conversation.h" +#include "api/newdevicemodel.h" + +#include "lrcinstance.h" + +class VideoInputDeviceModel : public QAbstractListModel +{ + Q_OBJECT +public: + enum Role { + DeviceChannel = Qt::UserRole + 1, + DeviceName, + DeviceId, + CurrentFrameRate, + CurrentResolution, + DeviceName_UTF8 + }; + Q_ENUM(Role) + + explicit VideoInputDeviceModel(QObject *parent = 0); + ~VideoInputDeviceModel(); + + /* + * QAbstractListModel override. + */ + int rowCount(const QModelIndex &parent = QModelIndex()) const override; + int columnCount(const QModelIndex &parent) const override; + QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override; + /* + * Override role name as access point in qml. + */ + QHash roleNames() const override; + QModelIndex index(int row, int column = 0, const QModelIndex &parent = QModelIndex()) const; + QModelIndex parent(const QModelIndex &child) const; + Qt::ItemFlags flags(const QModelIndex &index) const; + + /* + * This function is to reset the model when there's new account added. + */ + Q_INVOKABLE void reset(); + /* + * This function is to reset the model when there's new account added. + */ + Q_INVOKABLE int deviceCount(); + /* + * This function is to get the current device id in the demon. + */ + Q_INVOKABLE int getCurrentSettingIndex(); +}; diff --git a/src/webchathelpers.cpp b/src/webchathelpers.cpp new file mode 100644 index 00000000..273948c3 --- /dev/null +++ b/src/webchathelpers.cpp @@ -0,0 +1,150 @@ +/* + * Copyright (C) 2017-2020 by Savoir-faire Linux + * Author: Alexandre Viau + * Author: S�bastien Blin + * Author: Hugo Lefeuvre + * Author: Andreas Traczyk + * + * 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 . + */ + +#include "webchathelpers.h" + +QJsonObject +buildInteractionJson(lrc::api::ConversationModel &conversationModel, + const uint64_t msgId, + const lrc::api::interaction::Info &inter) +{ + + QRegExp reg(".(jpeg|jpg|gif|png)$"); + auto interaction = inter; + if (interaction.type == lrc::api::interaction::Type::DATA_TRANSFER && + interaction.body.toLower().contains(reg)) { + interaction.body = "file://" + interaction.body; + } + + auto sender = interaction.authorUri; + auto timestamp = QString::number(interaction.timestamp); + auto direction = lrc::api::interaction::isOutgoing(interaction) ? QString("out") + : QString("in"); + + QJsonObject interactionObject = QJsonObject(); + interactionObject.insert("text", QJsonValue(interaction.body)); + interactionObject.insert("id", QJsonValue(QString::number(msgId))); + interactionObject.insert("sender", QJsonValue(sender)); + interactionObject.insert("sender_contact_method", QJsonValue(sender)); + interactionObject.insert("timestamp", QJsonValue(timestamp)); + interactionObject.insert("direction", QJsonValue(direction)); + interactionObject.insert("duration", QJsonValue(static_cast(interaction.duration))); + + switch (interaction.type) { + case lrc::api::interaction::Type::TEXT: + interactionObject.insert("type", QJsonValue("text")); + break; + case lrc::api::interaction::Type::CALL: + interactionObject.insert("type", QJsonValue("call")); + break; + case lrc::api::interaction::Type::CONTACT: + interactionObject.insert("type", QJsonValue("contact")); + break; + case lrc::api::interaction::Type::DATA_TRANSFER: { + interactionObject.insert("type", QJsonValue("data_transfer")); + lrc::api::datatransfer::Info info = {}; + conversationModel.getTransferInfo(msgId, info); + if (info.status != lrc::api::datatransfer::Status::INVALID) { + interactionObject.insert("totalSize", QJsonValue(qint64(info.totalSize))); + interactionObject.insert("progress", QJsonValue(qint64(info.progress))); + } + break; + } + case lrc::api::interaction::Type::INVALID: + default: + return {}; + } + + if (interaction.isRead) { + interactionObject.insert("delivery_status", QJsonValue("read")); + } + + switch (interaction.status) { + case lrc::api::interaction::Status::SUCCESS: + interactionObject.insert("delivery_status", QJsonValue("sent")); + break; + case lrc::api::interaction::Status::FAILURE: + case lrc::api::interaction::Status::TRANSFER_ERROR: + interactionObject.insert("delivery_status", QJsonValue("failure")); + break; + case lrc::api::interaction::Status::TRANSFER_UNJOINABLE_PEER: + interactionObject.insert("delivery_status", QJsonValue("unjoinable peer")); + break; + case lrc::api::interaction::Status::SENDING: + interactionObject.insert("delivery_status", QJsonValue("sending")); + break; + case lrc::api::interaction::Status::TRANSFER_CREATED: + interactionObject.insert("delivery_status", QJsonValue("connecting")); + break; + case lrc::api::interaction::Status::TRANSFER_ACCEPTED: + interactionObject.insert("delivery_status", QJsonValue("accepted")); + break; + case lrc::api::interaction::Status::TRANSFER_CANCELED: + interactionObject.insert("delivery_status", QJsonValue("canceled")); + break; + case lrc::api::interaction::Status::TRANSFER_ONGOING: + interactionObject.insert("delivery_status", QJsonValue("ongoing")); + break; + case lrc::api::interaction::Status::TRANSFER_AWAITING_PEER: + interactionObject.insert("delivery_status", QJsonValue("awaiting peer")); + break; + case lrc::api::interaction::Status::TRANSFER_AWAITING_HOST: + interactionObject.insert("delivery_status", QJsonValue("awaiting host")); + break; + case lrc::api::interaction::Status::TRANSFER_TIMEOUT_EXPIRED: + interactionObject.insert("delivery_status", QJsonValue("awaiting peer timeout")); + break; + case lrc::api::interaction::Status::TRANSFER_FINISHED: + interactionObject.insert("delivery_status", QJsonValue("finished")); + break; + case lrc::api::interaction::Status::INVALID: + case lrc::api::interaction::Status::UNKNOWN: + default: + interactionObject.insert("delivery_status", QJsonValue("unknown")); + break; + } + return interactionObject; +} + +QString +interactionToJsonInteractionObject(lrc::api::ConversationModel &conversationModel, + const uint64_t msgId, + const lrc::api::interaction::Info &interaction) +{ + auto interactionObject = buildInteractionJson(conversationModel, msgId, interaction); + return QString(QJsonDocument(interactionObject).toJson(QJsonDocument::Compact)); +} + +QString +interactionsToJsonArrayObject(lrc::api::ConversationModel &conversationModel, + const std::map interactions) +{ + QJsonArray array; + for (const auto &interaction : interactions) { + auto interactionObject = buildInteractionJson(conversationModel, + interaction.first, + interaction.second); + if (!interactionObject.isEmpty()) { + array.append(interactionObject); + } + } + return QString(QJsonDocument(array).toJson(QJsonDocument::Compact)); +} diff --git a/src/webchathelpers.h b/src/webchathelpers.h new file mode 100644 index 00000000..f44dd620 --- /dev/null +++ b/src/webchathelpers.h @@ -0,0 +1,39 @@ +/* + * Copyright (C) 2017-2020 by Savoir-faire Linux + * Author: Alexandre Viau + * Author: Sébastien Blin + * Author: Hugo Lefeuvre + * Author: Andreas Traczyk + * + * 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 . + */ + +#pragma once + +#include +#include +#include +#include + +#include "api/conversationmodel.h" + +QJsonObject buildInteractionJson(lrc::api::ConversationModel &conversationModel, + const uint64_t msgId, + const lrc::api::interaction::Info &interaction); +QString interactionToJsonInteractionObject(lrc::api::ConversationModel &conversationModel, + const uint64_t msgId, + const lrc::api::interaction::Info &interaction); +QString interactionsToJsonArrayObject( + lrc::api::ConversationModel &conversationModel, + const std::map interactions); diff --git a/src/wizardview/WizardView.qml b/src/wizardview/WizardView.qml new file mode 100644 index 00000000..0f3c29da --- /dev/null +++ b/src/wizardview/WizardView.qml @@ -0,0 +1,736 @@ +/* + * Copyright (C) 2020 by Savoir-faire Linux + * Author: Yang Wang + * + * 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 . + */ + +import QtQuick 2.14 +import QtQuick.Window 2.14 +import QtQuick.Controls 1.4 as CT +import QtQuick.Controls 2.14 +import QtQuick.Controls.Universal 2.12 +import QtQuick.Layouts 1.3 +import QtGraphicalEffects 1.14 +import net.jami.Models 1.0 + +import "../commoncomponents" +import "../constant" +import "components" + +Window { + id: wizardViewWindow + + enum Mode { + CREATE, + IMPORT, + MIGRATE, + CREATESIP, + CONNECTMANAGER + } + + enum NameRegistrationState { + BLANK, + INVALID, + TAKEN, + FREE, + SEARCHING + } + + property int layoutWidth: 768 + property int layoutHeight: 768 + property int textFontSize: 9 + property int wizardMode: WizardView.CREATE + property int addedAccountIndex: -1 + property bool registrationStateOk: false + property string fileToImport: "" + property string registedName: "" + + property var inputParaObject: ({}) + + /* + * signal to redirect the page to main view + */ + signal needToShowMainViewWindow(int accountIndex) + signal wizardViewIsClosed + + title: "Jami" + visible: true + width: layoutWidth + height: layoutHeight + + onClosing: { + close.accepted = false + changePageQML(controlPanelStackView.welcomePageStackId) + wizardViewWindow.hide() + wizardViewWindow.wizardViewIsClosed() + } + + Component.onCompleted: { + changePageQML( + controlPanelStackView.welcomePageStackId) + } + + Connections{ + target: ClientWrapper.accountAdaptor + + function onAccountAdded(showBackUp, index) { + addedAccountIndex = index + if (showBackUp) { + changePageQML(controlPanelStackView.backupKeysPageId) + } else { + wizardViewWindow.hide() + changePageQML(controlPanelStackView.welcomePageStackId) + needToShowMainViewWindow(addedAccountIndex) + ClientWrapper.lrcInstance.accountListChanged() + } + } + + // reportFailure + function onReportFailure() { + reportFailureQML() + } + } + + Connections { + id: registeredNameFoundConnection + target: ClientWrapper.nameDirectory + enabled: false + + function onRegisteredNameFound(status, address, name) { + slotRegisteredNameFound(status, address, name) + } + } + + // failure redirect timer and qml object holder + Timer { + id: failureRedirectPageTimer + + repeat: false + triggeredOnStart: false + interval: 1000 + + onTriggered: { + spinnerPage.successState = true + } + } + + function reportFailureQML() { + spinnerPage.successState = false + failureRedirectPageTimer.restart() + } + + function createAccountQML() { + switch (wizardMode) { + case WizardView.CONNECTMANAGER: + ClientWrapper.accountAdaptor.createJAMSAccount(inputParaObject) + break + case WizardView.CREATE: + case WizardView.IMPORT: + ClientWrapper.accountAdaptor.createJamiAccount(registedName, + inputParaObject, + createAccountPage.boothImgBase64, + (wizardMode === WizardView.CREATE)) + break + default: + ClientWrapper.accountAdaptor.createSIPAccount(inputParaObject,createSIPAccountPage.boothImgBase64) + } + + changePageQML(controlPanelStackView.spinnerPageId) + update() + } + + function slotRegisteredNameFound(status, address, name) { + if (name.length < 3) { + registrationStateOk = false + createAccountPage.nameRegistrationUIState = WizardView.INVALID + } else if (registedName === name) { + switch (status) { + case NameDirectory.LookupStatus.NOT_FOUND: + case NameDirectory.LookupStatus.ERROR: + registrationStateOk = true + createAccountPage.nameRegistrationUIState = WizardView.FREE + break + case NameDirectory.LookupStatus.INVALID_NAME: + case NameDirectory.LookupStatus.INVALID: + registrationStateOk = false + createAccountPage.nameRegistrationUIState = WizardView.INVALID + break + case NameDirectory.LookupStatus.SUCCESS: + registrationStateOk = false + createAccountPage.nameRegistrationUIState = WizardView.TAKEN + break + } + } + validateWizardProgressionQML() + } + + // function to set up nav bar visibility and the three buttons' visibiliy + function setNavBarVisibility(navVisible, back) { + navBarView.visible = (navVisible == true) || (back == true) + btnNext.visible = (navVisible == true) + btnPevious.visible = (navVisible == true) + btnBack.visible = (back == true) + && (ClientWrapper.utilsAdaptor.getAccountListSize() != 0) + } + + function processWizardInformationsQML() { + inputParaObject = {} + switch (wizardMode) { + case WizardView.CREATE: + spinnerPage.progressLabelEditText = qsTr( + "Generating your Jami account...") + inputParaObject["alias"] = createAccountPage.text_fullNameEditAlias + + inputParaObject["password"] = createAccountPage.text_confirmPasswordEditAlias + + createAccountPage.clearAllTextFields() + break + case WizardView.IMPORT: + registedName = "" + spinnerPage.progressLabelEditText = qsTr( + "Importing account archive...") + // should only work in import from backup page or import from device page + if (controlPanelStackView.currentIndex + == controlPanelStackView.importFromBackupPageId) { + inputParaObject["password"] + = importFromBackupPage.text_passwordFromDeviceAlias + importFromBackupPage.clearAllTextFields() + } else if (controlPanelStackView.currentIndex + == controlPanelStackView.importFromDevicePageId) { + inputParaObject["archivePin"] = importFromBackupPage.text_pinFromDeviceAlias + inputParaObject["password"] + = importFromDevicePage.text_passwordFromDeviceAlias + importFromDevicePage.clearAllTextFields() + } + break + case WizardView.MIGRATE: + spinnerPage.progressLabelEditText = qsTr( + "Migrating your Jami account...") + break + case WizardView.CREATESIP: + spinnerPage.progressLabelEditText = qsTr( + "Generating your SIP account...") + if (createSIPAccountPage.text_sipFullNameEditAlias.length == 0) { + inputParaObject["alias"] = "SIP" + } else { + inputParaObject["alias"] = createSIPAccountPage.text_sipFullNameEditAlias + } + + inputParaObject["hostname"] = createSIPAccountPage.text_sipServernameEditAlias + inputParaObject["username"] = createSIPAccountPage.text_sipUsernameEditAlias + inputParaObject["password"] = createSIPAccountPage.text_sipPasswordEditAlias + inputParaObject["proxy"] = createSIPAccountPage.text_sipProxyEditAlias + + break + case WizardView.CONNECTMANAGER: + spinnerPage.progressLabelEditText = qsTr( + "Connecting to account manager...") + inputParaObject["username"] + = connectToAccountManagerPage.text_usernameManagerEditAlias + inputParaObject["password"] + = connectToAccountManagerPage.text_passwordManagerEditAlias + inputParaObject["manager"] + = connectToAccountManagerPage.text_accountManagerEditAlias + connectToAccountManagerPage.clearAllTextFields() + break + } + + inputParaObject["archivePath"] = fileToImport + + if (!("archivePin" in inputParaObject)) { + inputParaObject["archivePath"] = "" + } + + // change page to spinner page + changePageQML(controlPanelStackView.spinnerPageId) + //create account + createAccountQML() + ClientWrapper.utilsAdaptor.createStartupLink() + } + + function changePageQML(pageIndex) { + if (pageIndex == controlPanelStackView.spinnerPageId) { + setNavBarVisibility(false) + } + controlPanelStackView.currentIndex = pageIndex + if (pageIndex == controlPanelStackView.welcomePageStackId) { + fileToImport = "" + setNavBarVisibility(false, true) + createAccountPage.nameRegistrationUIState = WizardView.BLANK + } else if (pageIndex == controlPanelStackView.createAccountPageId) { + createAccountPage.initializeOnShowUp() + setNavBarVisibility(true) + // connection between register name found and its slot + registeredNameFoundConnection.enabled = true + // validate wizard progression + validateWizardProgressionQML() + // start photobooth + createAccountPage.startBooth() + } else if (pageIndex == controlPanelStackView.createSIPAccountPageId) { + createSIPAccountPage.initializeOnShowUp() + setNavBarVisibility(true) + btnNext.enabled = true + // start photo booth + createSIPAccountPage.startBooth() + } else if (pageIndex == controlPanelStackView.importFromDevicePageId) { + importFromDevicePage.initializeOnShowUp() + setNavBarVisibility(true) + } else if (pageIndex == controlPanelStackView.spinnerPageId) { + createAccountPage.nameRegistrationUIState = WizardView.BLANK + createAccountPage.isToSetPassword_checkState_choosePasswordCheckBox = false + } else if (pageIndex == controlPanelStackView.connectToAccountManagerPageId) { + setNavBarVisibility(true) + connectToAccountManagerPage.initializeOnShowUp() + btnNext.enabled = false + } else if (pageIndex == controlPanelStackView.importFromBackupPageId) { + setNavBarVisibility(true) + importFromBackupPage.clearAllTextFields() + fileToImport = "" + btnNext.enabled = false + } else if (pageIndex == controlPanelStackView.backupKeysPageId) { + setNavBarVisibility(false) + } + } + + function validateWizardProgressionQML() { + if (controlPanelStackView.currentIndex + == controlPanelStackView.importFromDevicePageId) { + var validPin = !(importFromDevicePage.text_pinFromDeviceAlias.length == 0) + btnNext.enabled = validPin + return + } else if (controlPanelStackView.currentIndex + == controlPanelStackView.connectToAccountManagerPageId) { + var validUsername = !(connectToAccountManagerPage.text_usernameManagerEditAlias.length == 0) + var validPassword = !(connectToAccountManagerPage.text_passwordManagerEditAlias.length == 0) + var validManager = !(connectToAccountManagerPage.text_accountManagerEditAlias.length == 0) + btnNext.enabled = validUsername && validPassword + && validManager + return + } else if (controlPanelStackView.currentIndex + == controlPanelStackView.importFromBackupPageId) { + var validImport = !(fileToImport.length == 0) + btnNext.enabled = validImport + return + } + + var usernameOk = !createAccountPage.checkState_signUpCheckboxAlias + || (createAccountPage.checkState_signUpCheckboxAlias + && !(registedName.length == 0) + && (registedName == createAccountPage.text_usernameEditAlias) + && (registrationStateOk == true)) + var passwordOk = (createAccountPage.text_passwordEditAlias + == createAccountPage.text_confirmPasswordEditAlias) + + // set password status label + if (passwordOk + && !(createAccountPage.text_passwordEditAlias.length == 0)) { + createAccountPage.displayState_passwordStatusLabelAlias = "Success" + } else if (!passwordOk) { + createAccountPage.displayState_passwordStatusLabelAlias = "Fail" + } else { + createAccountPage.displayState_passwordStatusLabelAlias = "Hide" + } + //set enable state of next button + btnNext.enabled = (usernameOk && passwordOk) + } + + PasswordDialog { + id: passwordDialog + + anchors.centerIn: parent.Center + x: (parent.width - width) / 2 + y: (parent.height - height) / 2 + + visible: false + purpose: PasswordDialog.ExportAccount + + onDoneSignal: { + if (currentPurpose === passwordDialog.ExportAccount) { + var success = (code === successCode) + + var title = success ? qsTr("Success") : qsTr("Error") + var info = success ? qsTr("Export Successful") : qsTr( + "Export Failed") + + ClientWrapper.accountAdaptor.passwordSetStatusMessageBox(success, + title, info) + if (success) { + console.log("Account Export Succeed") + wizardViewWindow.hide() + needToShowMainViewWindow(addedAccountIndex) + ClientWrapper.lrcInstance.accountListChanged() + } + } + } + } + + MouseArea { + anchors.fill: parent + onClicked: forceActiveFocus() + } + + // main frame rectangle + ScrollView { + id: wizardViewRect + anchors.fill: parent + + clip: true + + ColumnLayout { + id: content + width: wizardViewWindow.width // ensure correct width + height: wizardViewWindow.height // ensure correct height + + Layout.alignment: Qt.AlignHCenter + RowLayout { + Layout.alignment: Qt.AlignHCenter + Layout.fillWidth: true + Layout.fillHeight: true + + StackLayout { + id: controlPanelStackView + currentIndex: welcomePageStackId + Layout.fillWidth: true + Layout.fillHeight: true + + property int welcomePageStackId: 0 + property int createAccountPageId: 1 + property int createSIPAccountPageId: 2 + property int importFromBackupPageId: 3 + property int backupKeysPageId: 4 + property int importFromDevicePageId: 5 + property int connectToAccountManagerPageId: 6 + property int spinnerPageId: 7 + + WelcomePageLayout { + // welcome page, index 0 + id: welcomePage + + onWelcomePageRedirectPage: { + changePageQML(toPageIndex) + } + + onVisibleChanged: { + if (visible) + setNavBarVisibility(false, + true) + } + + Component.onCompleted: { + setNavBarVisibility(false, true) + } + } + + CreateAccountPage { + // create account page, index 1 + id: createAccountPage + + onText_usernameEditAliasChanged: { + registrationStateOk = false + if (createAccountPage.checkState_signUpCheckboxAlias + && (createAccountPage.text_usernameEditAlias.length != 0)) { + registedName = ClientWrapper.utilsAdaptor.stringSimplifier( + createAccountPage.text_usernameEditAlias) + lookupTimer.restart() + } else { + createAccountPage.nameRegistrationUIState = WizardView.BLANK + lookupTimer.stop() + if (createAccountPage.text_usernameEditAlias.length == 0) { + lookupTimer.restart() + } + } + validateWizardProgressionQML() + } + + onValidateWizardProgressionCreateAccountPage: { + validateWizardProgressionQML() + } + + onText_passwordEditAliasChanged: { + validateWizardProgressionQML() + } + + onText_confirmPasswordEditAliasChanged: { + validateWizardProgressionQML() + } + + Timer { + id: lookupTimer + + repeat: false + triggeredOnStart: false + interval: 200 + + onTriggered: { + if (createAccountPage.checkState_signUpCheckboxAlias + && (createAccountPage.text_usernameEditAlias.length != 0)) { + createAccountPage.nameRegistrationUIState = WizardView.SEARCHING + ClientWrapper.nameDirectory.lookupName("", registedName) + } + } + } + } + + CreateSIPAccountPage { + // create SIP account page, index 2 + id: createSIPAccountPage + } + + ImportFromBackupPage { + // import from backup page, index 3 + id: importFromBackupPage + + onText_passwordFromBackupEditAliasChanged: { + validateWizardProgressionQML() + } + + onImportFromFile_Dialog_Accepted: { + fileToImport = ClientWrapper.utilsAdaptor.toNativeSeparators(fileDir) + inputParaObject[""] + + if (fileToImport.length != 0) { + importFromBackupPage.fileImportBtnText = ClientWrapper.utilsAdaptor.toFileInfoName( + fileToImport) + } else { + importFromBackupPage.fileImportBtnText = qsTr( + "Archive(none)") + } + validateWizardProgressionQML() + } + } + + BackupKeyPage { + // backup keys page, index 4 + id: backupKeysPage + + onNeverShowAgainBoxClicked: { + ClientWrapper.accountAdaptor.settingsNeverShowAgain(isChecked) + } + + onExport_Btn_FileDialogAccepted: { + if (accepted) { + // is there password? If so, go to password dialog, else, go to following directly + if (ClientWrapper.accountAdaptor.hasPassword()) { + passwordDialog.path = ClientWrapper.utilsAdaptor.getAbsPath(folderDir) + passwordDialog.open() + return + } else { + if (folderDir.length > 0) { + ClientWrapper.accountAdaptor.exportToFile( + ClientWrapper.utilsAdaptor.getCurrAccId(), + ClientWrapper.utilsAdaptor.getAbsPath(folderDir)) + } + } + } + + wizardViewWindow.hide() + changePageQML(controlPanelStackView.welcomePageStackId) + needToShowMainViewWindow(addedAccountIndex) + ClientWrapper.lrcInstance.accountListChanged() + } + + + onSkip_Btn_Clicked: { + wizardViewWindow.hide() + changePageQML(controlPanelStackView.welcomePageStackId) + needToShowMainViewWindow(addedAccountIndex) + ClientWrapper.lrcInstance.accountListChanged() + } + } + + ImportFromDevicePage { + // import from device page, index 5 + id: importFromDevicePage + + onText_pinFromDeviceAliasChanged: { + validateWizardProgressionQML() + } + + onText_passwordFromDeviceAliasChanged: { + validateWizardProgressionQML() + } + } + + ConnectToAccountManagerPage { + // connect to account manager Page, index 6 + id: connectToAccountManagerPage + + onText_usernameManagerEditAliasChanged: { + validateWizardProgressionQML() + } + + onText_passwordManagerEditAliasChanged: { + validateWizardProgressionQML() + } + + onText_accountManagerEditAliasChanged: { + validateWizardProgressionQML() + } + } + + SpinnerPage { + // spinner Page, index 7 + id: spinnerPage + } + } + } + + RowLayout { + id: navBarView + + Layout.alignment: Qt.AlignHCenter | Qt.AlignBottom + Layout.fillWidth: true + + Layout.maximumHeight: 52 + Layout.preferredHeight: 52 + + HoverableGradientButton { + id: btnPevious + Layout.alignment: Qt.AlignLeft + width: 85 + height: 30 + radius: height / 2 + + Layout.leftMargin: 11 + + Layout.preferredWidth: 85 + Layout.preferredHeight: 30 + text: qsTr("Previous") + font.pointSize: 10 + font.kerning: true + + onClicked: { + // stop photobooth previewing + if(controlPanelStackView.currentIndex == controlPanelStackView.createAccountPageId) { + createAccountPage.stopBooth() + } + if(controlPanelStackView.currentIndex == controlPanelStackView.createSIPAccountPageId) { + createSIPAccountPage.stopBooth() + } + + // Disconnect registered name found Connection + registeredNameFoundConnection.enabled = false + // deal with look up status label and collapsible password widget + createAccountPage.nameRegistrationUIState = WizardView.BLANK + createAccountPage.isToSetPassword_checkState_choosePasswordCheckBox = false + // switch to welcome page + if (controlPanelStackView.currentIndex + == controlPanelStackView.createAccountPageId + || controlPanelStackView.currentIndex + == controlPanelStackView.createSIPAccountPageId + || controlPanelStackView.currentIndex + == controlPanelStackView.importFromBackupPageId + || controlPanelStackView.currentIndex + == controlPanelStackView.importFromDevicePageId + || controlPanelStackView.currentIndex + == controlPanelStackView.connectToAccountManagerPageId) { + changePageQML( + controlPanelStackView.welcomePageStackId) + } + } + } + + Item { + Layout.alignment: Qt.AlignHCenter + Layout.fillHeight: true + Layout.minimumWidth: 40 + Layout.fillWidth: true + } + + HoverableGradientButton { + id: btnBack + Layout.alignment: Qt.AlignLeft + width: 85 + height: 30 + radius: height / 2 + + Layout.preferredWidth: 85 + Layout.preferredHeight: 30 + text: qsTr("Back") + font.pointSize: 10 + font.kerning: true + + onClicked: { + wizardViewWindow.hide() + needToShowMainViewWindow(addedAccountIndex) + } + } + + Item { + Layout.alignment: Qt.AlignHCenter + Layout.fillHeight: true + Layout.minimumWidth: 40 + Layout.fillWidth: true + } + + HoverableGradientButton { + id: btnNext + Layout.alignment: Qt.AlignRight + width: 85 + height: 30 + radius: height / 2 + + Layout.rightMargin: 11 + + Layout.minimumWidth: 85 + Layout.preferredWidth: 85 + Layout.maximumWidth: 85 + + Layout.minimumHeight: 30 + Layout.preferredHeight: 30 + Layout.maximumHeight: 30 + + text: qsTr("Next") + font.pointSize: 10 + font.kerning: true + + onClicked: { + // stop photobooth previewing + if(controlPanelStackView.currentIndex == controlPanelStackView.createAccountPageId) { + createAccountPage.stopBooth() + } + if(controlPanelStackView.currentIndex == controlPanelStackView.createSIPAccountPageId) { + createSIPAccountPage.stopBooth() + } + + registeredNameFoundConnection.enabled = false + + if (controlPanelStackView.currentIndex + == controlPanelStackView.createAccountPageId) { + wizardMode = WizardView.CREATE + processWizardInformationsQML() + } else if (controlPanelStackView.currentIndex + == controlPanelStackView.importFromDevicePageId) { + wizardMode = WizardView.IMPORT + processWizardInformationsQML() + } else if (controlPanelStackView.currentIndex + == controlPanelStackView.createSIPAccountPageId) { + wizardMode = WizardView.CREATESIP + processWizardInformationsQML() + } else if (controlPanelStackView.currentIndex + == controlPanelStackView.connectToAccountManagerPageId) { + wizardMode = WizardView.CONNECTMANAGER + processWizardInformationsQML() + } else if (controlPanelStackView.currentIndex + == controlPanelStackView.importFromBackupPageId) { + wizardMode = WizardView.IMPORT + processWizardInformationsQML() + } + } + } + } + } + } +} diff --git a/src/wizardview/components/BackupKeyPage.qml b/src/wizardview/components/BackupKeyPage.qml new file mode 100644 index 00000000..59ec3ef7 --- /dev/null +++ b/src/wizardview/components/BackupKeyPage.qml @@ -0,0 +1,200 @@ +/* + * Copyright (C) 2020 by Savoir-faire Linux + * Author: Yang Wang + * + * 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 . + */ + +import QtQuick 2.14 +import QtQuick.Layouts 1.3 +import QtQuick.Controls 2.14 +import Qt.labs.platform 1.1 + +import "../../constant" +import "../../commoncomponents" + +ColumnLayout { + signal neverShowAgainBoxClicked(bool isChecked) + signal skip_Btn_Clicked + signal export_Btn_FileDialogAccepted(bool accepted, string folderDir) + + /* + * JamiFileDialog for exporting account + */ + JamiFileDialog { + id: exportBtn_Dialog + + mode: JamiFileDialog.SaveFile + + title: qsTr("Export Account Here") + folder: StandardPaths.writableLocation(StandardPaths.HomeLocation) + "/Desktop" + + nameFilters: [qsTr("Jami archive files") + " (*.gz)", qsTr( + "All files") + " (*)"] + + onAccepted: { + export_Btn_FileDialogAccepted(true, file) + } + + onRejected: { + export_Btn_FileDialogAccepted(false, folder) + } + + onVisibleChanged: { + if (!visible) { + rejected() + } + } + } + + Layout.fillWidth: true + Layout.fillHeight: true + + Item { + Layout.alignment: Qt.AlignHCenter + Layout.fillWidth: true + Layout.fillHeight: true + } + + /* + * Main layout for BackupKeyPage which consists of the buttons and "never show again" check box + */ + ColumnLayout { + Layout.alignment: Qt.AlignCenter + Layout.maximumWidth: 366 + + spacing: 12 + + Label { + id: backupKeysLabel + Layout.alignment: Qt.AlignHCenter + + Layout.maximumWidth: 366 + Layout.maximumHeight: 21 + Layout.preferredWidth: 366 + Layout.preferredHeight: 21 + + text: qsTr("Backup your account") + font.pointSize: 13 + font.kerning: true + } + Label { + id: backupInfoLabel1 + Layout.maximumWidth: 366 + Layout.maximumHeight: 57 + Layout.preferredWidth: 366 + Layout.preferredHeight: 57 + + text: qsTr("This account only exists on this device. If you lost your device or uninstall the application,your account will be deleted. You can backup your account now or later.") + wrapMode: Text.WordWrap + horizontalAlignment: Text.AlignJustify + verticalAlignment: Text.AlignVCenter + } + CheckBox { + id: neverShowAgainBox + checked: false + + Layout.maximumWidth: 366 + Layout.maximumHeight: 19 + Layout.preferredWidth: 366 + Layout.preferredHeight: 19 + + indicator.implicitWidth: 10 + indicator.implicitHeight:10 + + text: qsTr("Never show me this again") + font.pointSize: 8 + + onClicked: { + neverShowAgainBoxClicked(checked) + } + } + RowLayout { + Layout.fillWidth: true + Layout.maximumHeight: 20 + + Item { + Layout.alignment: Qt.AlignVCenter + Layout.fillHeight: true + Layout.maximumWidth: 40 + Layout.minimumWidth: 10 + } + + HoverableGradientButton { + id: exportBtn + + Layout.alignment: Qt.AlignVCenter + Layout.minimumWidth: 85 + Layout.preferredWidth: 85 + Layout.maximumWidth: 85 + + Layout.minimumHeight: 30 + Layout.preferredHeight: 30 + Layout.maximumHeight: 30 + + text: qsTr("Export") + font.kerning: true + fontPointSize: 10 + radius: height / 2 + backgroundColor: JamiTheme.releaseColor + + onClicked: { + exportBtn_Dialog.open() + } + } + + Item { + Layout.alignment: Qt.AlignVCenter + Layout.fillWidth: true + Layout.fillHeight: true + } + + HoverableGradientButton { + id: skipBtn + + Layout.alignment: Qt.AlignVCenter + Layout.minimumWidth: 85 + Layout.preferredWidth: 85 + Layout.maximumWidth: 85 + + Layout.minimumHeight: 30 + Layout.preferredHeight: 30 + Layout.maximumHeight: 30 + + text: qsTr("Skip") + fontPointSize: 10 + font.kerning: true + radius: height / 2 + backgroundColor: JamiTheme.releaseColor + + onClicked: { + skip_Btn_Clicked() + } + } + + Item { + Layout.alignment: Qt.AlignVCenter + Layout.fillHeight: true + Layout.maximumWidth: 40 + Layout.minimumWidth: 10 + } + } + } + + Item { + Layout.alignment: Qt.AlignHCenter + Layout.fillWidth: true + Layout.fillHeight: true + } +} diff --git a/src/wizardview/components/CollapsiblePasswordWidget.qml b/src/wizardview/components/CollapsiblePasswordWidget.qml new file mode 100644 index 00000000..82af6e2b --- /dev/null +++ b/src/wizardview/components/CollapsiblePasswordWidget.qml @@ -0,0 +1,156 @@ +/* + * Copyright (C) 2020 by Savoir-faire Linux + * Author: Yang Wang + * + * 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 . + */ + +import QtQuick 2.14 +import QtQuick.Layouts 1.3 +import QtQuick.Controls 2.14 + +import "../../constant" +import "../../commoncomponents" + +/* + * an independent widget that keeps the password's textfields, including password field and confirm password field + */ + +GridLayout { + id: root + + property alias text_passwordEditAlias: passwordEdit.text + property alias text_confirmPasswordEditAlias: confirmPasswordEdit.text + property alias state_passwordStatusLabelAlias: passwordStatusLabel.passwordStatusState + + property bool visibleCollapsble: false + + function clearAllTextFields() { + passwordEdit.clear() + confirmPasswordEdit.clear() + } + + visible: visibleCollapsble + Layout.fillWidth: true + rowSpacing: 6 + columnSpacing: 6 + + rows: 2 + columns: 2 + + Layout.leftMargin: 32 + + InfoLineEdit { + id: passwordEdit + + visible: visibleCollapsble + + Layout.row: 0 + Layout.column: 0 + + fieldLayoutWidth: 261 + + Layout.alignment: Qt.AlignHCenter + + selectByMouse: true + echoMode: TextInput.Password + placeholderText: qsTr("Password") + font.pointSize: 10 + font.kerning: true + } + + Item { + Layout.row: 0 + Layout.column: 1 + + Layout.maximumWidth: 32 + Layout.preferredWidth: 32 + Layout.minimumWidth: 32 + + Layout.maximumHeight: 30 + Layout.preferredHeight: 30 + Layout.minimumHeight: 30 + } + + InfoLineEdit { + id: confirmPasswordEdit + + visible: visibleCollapsble + + Layout.row: 1 + Layout.column: 0 + + fieldLayoutWidth: 261 + + Layout.alignment: Qt.AlignHCenter + + selectByMouse: true + echoMode: TextInput.Password + placeholderText: qsTr("Confirm Password") + font.pointSize: 10 + font.kerning: true + } + + Label { + id: passwordStatusLabel + + visible: visibleCollapsble + + Layout.row: 1 + Layout.column: 1 + + Layout.maximumWidth: 32 + Layout.preferredWidth: 32 + Layout.minimumWidth: 32 + + Layout.maximumHeight: 30 + Layout.preferredHeight: 30 + Layout.minimumHeight: 30 + + Layout.alignment: Qt.AlignRight + + property string passwordStatusState: "Hide" + + background: { + switch (passwordStatusState) { + case "Hide": + return Qt.createQmlObject("import QtQuick 2.14; +import \"qrc:/src/constant/\"; +Rectangle { +anchors.fill: parent; +color: \"transparent\"; }", passwordStatusLabel) + case "Fail": + return Qt.createQmlObject("import QtQuick 2.14; +import \"qrc:/src/constant/\"; +Rectangle { +anchors.fill: parent; +Image{ +anchors.fill: parent; +source: \"image://tintedPixmap/\"+ (\"qrc:/images/icons/baseline-close-24px.svg\").replace(\"qrc:/images/icons/\",\"\") + \"+\" + JamiTheme.red_; +mipmap: true;} +}", passwordStatusLabel) + case "Success": + return Qt.createQmlObject("import QtQuick 2.14; +import \"qrc:/src/constant/\"; +Rectangle { +anchors.fill: parent; +Image { +anchors.fill: parent; +source: \"image://tintedPixmap/\"+ (\"qrc:/images/icons/baseline-done-24px.svg\").replace(\"qrc:/images/icons/\",\"\") + \"+\" + JamiTheme.presenceGreen_; +mipmap: true;} +}", passwordStatusLabel) + } + } + } +} diff --git a/src/wizardview/components/ConnectToAccountManagerPage.qml b/src/wizardview/components/ConnectToAccountManagerPage.qml new file mode 100644 index 00000000..c41dcef1 --- /dev/null +++ b/src/wizardview/components/ConnectToAccountManagerPage.qml @@ -0,0 +1,102 @@ +/* + * Copyright (C) 2020 by Savoir-faire Linux + * Author: Yang Wang + * + * 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 . + */ + +import QtQuick 2.14 +import QtQuick.Layouts 1.3 +import QtQuick.Controls 2.14 + +import "../../constant" +import "../../commoncomponents" + +ColumnLayout { + property alias text_usernameManagerEditAlias: usernameManagerEdit.text + property alias text_passwordManagerEditAlias: passwordManagerEdit.text + property alias text_accountManagerEditAlias: accountManagerEdit.text + + function initializeOnShowUp() { + clearAllTextFields() + } + + function clearAllTextFields() { + usernameManagerEdit.clear() + passwordManagerEdit.clear() + accountManagerEdit.clear() + } + + Layout.fillWidth: true + Layout.fillHeight: true + + Item { + Layout.alignment: Qt.AlignHCenter + Layout.preferredHeight: 40 + Layout.fillWidth: true + Layout.fillHeight: true + } + + ColumnLayout { + Layout.alignment: Qt.AlignCenter + Layout.fillWidth: true + + spacing: 12 + + Label { + id: signInLabel + + Layout.alignment: Qt.AlignHCenter + Layout.minimumWidth: 256 + Layout.preferredHeight: 21 + text: qsTr("Sign in") + font.pointSize: 13 + font.kerning: true + } + + InfoLineEdit { + id: usernameManagerEdit + + Layout.alignment: Qt.AlignHCenter + + selectByMouse: true + placeholderText: qsTr("Username") + } + + InfoLineEdit { + id: passwordManagerEdit + + Layout.alignment: Qt.AlignHCenter + selectByMouse: true + echoMode: TextInput.Password + placeholderText: qsTr("Password") + } + + InfoLineEdit { + id: accountManagerEdit + + Layout.alignment: Qt.AlignHCenter + + selectByMouse: true + placeholderText: qsTr("Account Manager") + } + } + + Item { + Layout.alignment: Qt.AlignHCenter + Layout.preferredHeight: 40 + Layout.fillWidth: true + Layout.fillHeight: true + } +} diff --git a/src/wizardview/components/CreateAccountPage.qml b/src/wizardview/components/CreateAccountPage.qml new file mode 100644 index 00000000..f59b2c6e --- /dev/null +++ b/src/wizardview/components/CreateAccountPage.qml @@ -0,0 +1,325 @@ +/* + * Copyright (C) 2020 by Savoir-faire Linux + * Author: Yang Wang + * + * 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 . + */ + +import QtQuick 2.14 +import QtQuick.Layouts 1.3 +import QtQuick.Controls 2.14 + +import "../" +import "../../constant" +import "../../commoncomponents" + +ColumnLayout { + property alias text_fullNameEditAlias: fullNameEdit.text + property alias text_usernameEditAlias: usernameEdit.text + + property int nameRegistrationUIState: WizardView.BLANK + + property alias checkState_signUpCheckboxAlias: signUpCheckbox.checked + property alias isToSetPassword_checkState_choosePasswordCheckBox: choosePasswordCheckBox.checked + + // photo booth alias + property alias boothImgBase64: setAvatarWidget.imgBase64 + + // collapse password widget property aliases + property alias text_passwordEditAlias: collapsiblePasswordWidget.text_passwordEditAlias + property alias text_confirmPasswordEditAlias: collapsiblePasswordWidget.text_confirmPasswordEditAlias + property alias displayState_passwordStatusLabelAlias: collapsiblePasswordWidget.state_passwordStatusLabelAlias + + signal validateWizardProgressionCreateAccountPage + + function initializeOnShowUp() { + clearAllTextFields() + + signUpCheckbox.checked = true + choosePasswordCheckBox.checked = false + usernameEdit.enabled = true + fullNameEdit.enabled = true + } + + function clearAllTextFields() { + usernameEdit.clear() + fullNameEdit.clear() + + collapsiblePasswordWidget.clearAllTextFields() + } + + function setCollapsiblePasswordWidgetVisibility(visible) { + choosePasswordCheckBox.checked = visible + if (visible) { + choosePasswordCheckBox.visible = true + } + } + + function startBooth(){ + setAvatarWidget.startBooth() + } + + function stopBooth(){ + setAvatarWidget.stopBooth() + } + + Layout.fillWidth: true + Layout.fillHeight: true + + spacing: 6 + + Item { + Layout.fillHeight: true + Layout.fillWidth: true + } + + ColumnLayout { + Layout.alignment: Qt.AlignHCenter + + spacing: 5 + + ColumnLayout { + Layout.fillWidth: true + spacing: 6 + + Layout.alignment: Qt.AlignHCenter + + Label { + id: profileSectionLabel + + + Layout.alignment: Qt.AlignHCenter + + text: qsTr("Profile") + font.pointSize: 13 + font.kerning: true + + horizontalAlignment: Text.AlignHCenter + verticalAlignment: Text.AlignVCenter + } + + PhotoboothView{ + id: setAvatarWidget + + Layout.alignment: Qt.AlignHCenter + + Layout.maximumWidth: 261 + Layout.preferredWidth: 261 + Layout.minimumWidth: 261 + Layout.maximumHeight: 261 + Layout.preferredHeight: 261 + Layout.minimumHeight: 261 + } + + RowLayout { + spacing: 6 + Layout.alignment: Qt.AlignHCenter + Layout.maximumHeight: 30 + + Item { + Layout.fillWidth: true + Layout.maximumHeight: 10 + } + + InfoLineEdit { + id: fullNameEdit + + fieldLayoutWidth: 261 + + Layout.alignment: Qt.AlignCenter + + selectByMouse: true + placeholderText: qsTr("Profile name") + font.pointSize: 10 + font.kerning: true + } + + Item { + Layout.fillHeight: true + Layout.fillWidth: true + } + } + } + } + + Item { + Layout.fillHeight: true + Layout.fillWidth: true + } + + ColumnLayout { + Layout.alignment: Qt.AlignHCenter + + spacing: 5 + Label { + id: accountSectionLabel + Layout.alignment: Qt.AlignHCenter + + Layout.maximumWidth: 261 + Layout.preferredWidth: 261 + Layout.minimumWidth: 261 + Layout.maximumHeight: 30 + Layout.preferredHeight: 30 + Layout.minimumHeight: 30 + + text: qsTr("Account") + font.pointSize: 13 + font.kerning: true + + horizontalAlignment: Text.AlignHCenter + verticalAlignment: Text.AlignVCenter + } + + ColumnLayout { + Layout.fillWidth: true + spacing: 6 + + CheckBox { + id: signUpCheckbox + checked: true + + indicator.width: 10 + indicator.height: 10 + + Layout.leftMargin: 32 + + Layout.minimumWidth: 261 + + Layout.maximumHeight: 30 + Layout.preferredHeight: 30 + Layout.minimumHeight: 25 + + Layout.alignment: Qt.AlignLeft + + text: qsTr("Register public username") + font.pointSize: 10 + font.kerning: true + + indicator.implicitWidth: 20 + indicator.implicitHeight:20 + + onClicked: { + if (!checked) { + usernameEdit.clear() + } + + validateWizardProgressionCreateAccountPage() + } + } + } + + RowLayout { + spacing: 6 + Layout.fillWidth: true + + Layout.leftMargin: 32 + + InfoLineEdit { + id: usernameEdit + + fieldLayoutWidth: 261 + + Layout.alignment: Qt.AlignHCenter + + selectByMouse: true + placeholderText: qsTr("Choose your username") + font.pointSize: 10 + font.kerning: true + + enabled: signUpCheckbox.visible && signUpCheckbox.checked + } + + LookupStatusLabel{ + id: lookupStatusLabel + + visible: true + + lookupStatusState: { + switch (nameRegistrationUIState) { + case WizardView.BLANK: + return "Blank" + case WizardView.INVALID: + return "Invalid" + case WizardView.TAKEN: + return "Taken" + case WizardView.FREE: + return "Free" + case WizardView.SEARCHING: + return "Searching" + default: + return "Blank" + } + } + } + } + + ColumnLayout { + Layout.fillWidth: true + spacing: 6 + + CheckBox { + id: choosePasswordCheckBox + checked: false + + indicator.width: 10 + indicator.height: 10 + + Layout.leftMargin: 32 + + Layout.minimumWidth: 261 + + Layout.preferredHeight: 30 + Layout.minimumHeight: 25 + + indicator.implicitWidth: 20 + indicator.implicitHeight:20 + + Layout.alignment: Qt.AlignLeft + + text: qsTr("Choose a password for enhanced security") + font.pointSize: 8 + font.kerning: true + + onClicked: { + if (!checked) { + collapsiblePasswordWidget.clearAllTextFields() + } + + validateWizardProgressionCreateAccountPage() + } + } + + CollapsiblePasswordWidget { + id: collapsiblePasswordWidget + + Layout.alignment: Qt.AlignHCenter + + visibleCollapsble: choosePasswordCheckBox.checked + && choosePasswordCheckBox.visible + } + } + + Item { + Layout.maximumWidth: 261 + Layout.preferredWidth: 261 + Layout.minimumWidth: 261 + + Layout.maximumHeight: 30 + Layout.preferredHeight: 30 + Layout.minimumHeight: 30 + + Layout.alignment: Qt.AlignHCenter + } + } +} diff --git a/src/wizardview/components/CreateSIPAccountPage.qml b/src/wizardview/components/CreateSIPAccountPage.qml new file mode 100644 index 00000000..3f3da172 --- /dev/null +++ b/src/wizardview/components/CreateSIPAccountPage.qml @@ -0,0 +1,202 @@ +/* + * Copyright (C) 2020 by Savoir-faire Linux + * Author: Yang Wang + * + * 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 . + */ + +import QtQuick 2.14 +import QtQuick.Layouts 1.3 +import QtQuick.Controls 2.14 + +import "../../constant" +import "../../commoncomponents" + +ColumnLayout { + property alias text_sipFullNameEditAlias: sipFullNameEdit.text + property alias text_sipServernameEditAlias: sipServernameEdit.text + property alias text_sipProxyEditAlias: sipProxyEdit.text + property alias text_sipUsernameEditAlias: sipUsernameEdit.text + property alias text_sipPasswordEditAlias: sipPasswordEdit.text + + property alias boothImgBase64: setSIPAvatarWidget.imgBase64 + + function initializeOnShowUp() { + clearAllTextFields() + } + + function clearAllTextFields() { + sipUsernameEdit.clear() + sipPasswordEdit.clear() + sipServernameEdit.clear() + sipProxyEdit.clear() + sipFullNameEdit.clear() + sipUsernameEdit.clear() + } + + function startBooth(){ + setSIPAvatarWidget.startBooth() + } + + function stopBooth(){ + setSIPAvatarWidget.stopBooth() + } + + Layout.fillWidth: true + Layout.fillHeight: true + + spacing: 6 + + Item { + Layout.fillHeight: true + Layout.fillWidth: true + } + + Label { + id: sipProfileSectionLabel + + Layout.maximumWidth: 368 + Layout.preferredWidth: 368 + Layout.maximumHeight: 21 + Layout.preferredHeight: 21 + + Layout.alignment: Qt.AlignHCenter + + text: qsTr("Profile") + font.pointSize: 13 + font.kerning: true + + horizontalAlignment: Text.AlignHCenter + verticalAlignment: Text.AlignVCenter + } + + PhotoboothView{ + id: setSIPAvatarWidget + + Layout.alignment: Qt.AlignHCenter + + Layout.maximumWidth: 261 + Layout.preferredWidth: 261 + Layout.minimumWidth: 261 + Layout.maximumHeight: 261 + Layout.preferredHeight: 261 + Layout.minimumHeight: 261 + } + + RowLayout { + spacing: 0 + Layout.alignment: Qt.AlignHCenter + Layout.maximumHeight: 30 + + Item { + Layout.fillWidth: true + Layout.maximumHeight: 10 + } + + InfoLineEdit { + id: sipFullNameEdit + + fieldLayoutWidth : 261 + Layout.alignment: Qt.AlignCenter + selectByMouse: true + placeholderText: qsTr("Profile name") + font.pointSize: 10 + font.kerning: true + } + + Item { + Layout.fillHeight: true + Layout.fillWidth: true + } + } + Item { + Layout.fillHeight: true + Layout.fillWidth: true + } + + Label { + id: sipAccountSectionLabel + Layout.maximumWidth: 368 + Layout.preferredWidth: 368 + Layout.maximumHeight: 21 + Layout.preferredHeight: 21 + + Layout.alignment: Qt.AlignHCenter + + text: qsTr("SIP Account") + font.pointSize: 12 + font.kerning: true + + horizontalAlignment: Text.AlignHCenter + verticalAlignment: Text.AlignVCenter + } + + ColumnLayout { + Layout.alignment: Qt.AlignHCenter + spacing: 7 + + Item { + Layout.fillWidth: true + Layout.alignment: Qt.AlignHCenter + Layout.maximumHeight: 40 + Layout.minimumHeight: 30 + Layout.preferredHeight: 40 + } + + InfoLineEdit { + id: sipServernameEdit + Layout.alignment: Qt.AlignHCenter + fieldLayoutWidth: 261 + + selectByMouse: true + placeholderText: qsTr("Server") + font.pointSize: 10 + font.kerning: true + } + + InfoLineEdit { + id: sipProxyEdit + Layout.alignment: Qt.AlignHCenter + fieldLayoutWidth: 261 + + selectByMouse: true + placeholderText: qsTr("Proxy") + font.pointSize: 10 + font.kerning: true + } + + InfoLineEdit { + id: sipUsernameEdit + Layout.alignment: Qt.AlignHCenter + fieldLayoutWidth: 261 + + selectByMouse: true + placeholderText: qsTr("Username") + font.pointSize: 10 + font.kerning: true + } + + InfoLineEdit { + id: sipPasswordEdit + Layout.alignment: Qt.AlignHCenter + fieldLayoutWidth: 261 + + selectByMouse: true + echoMode: TextInput.Password + placeholderText: qsTr("Password") + font.pointSize: 10 + font.kerning: true + } + } +} diff --git a/src/wizardview/components/HoverableGradientButton.qml b/src/wizardview/components/HoverableGradientButton.qml new file mode 100644 index 00000000..905bd41b --- /dev/null +++ b/src/wizardview/components/HoverableGradientButton.qml @@ -0,0 +1,142 @@ + +/* + * Copyright (C) 2020 by Savoir-faire Linux + * Author: Mingrui Zhang + * + * 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 . + */ +import QtQuick 2.15 +import QtQuick.Controls 2.14 +import QtGraphicalEffects 1.15 +import net.jami.Models 1.0 + + +/* + * HoverableButton contains the following configurable properties: + * 1. Color changes on different button state + * 2. Radius control (rounded) + * 3. Text content or image content + * 4. Can use OnClicked slot to implement some click logic + */ +Button { + id: hoverableButton + property int fontPointSize: 9 + property string backgroundColor: JamiTheme.releaseColor + property string backgroundColorDisabled : Qt.rgba(242/256, 242/256, 242/256, 0.8) + + property string startColor :"#109ede" + property string endColor : "#2b5084" + + property string startColorPressed :"#043161" + property string endColorPressed : "#00113f" + + property string startColorHovered :"#2b4b7e" + property string endColorHovered : "#001d4d" + + property string onPressColor: JamiTheme.pressColor + property string onReleaseColor: backgroundColor + property string onEnterColor: JamiTheme.hoverColor + property string onExitColor: backgroundColor + property string textColor: "white" + + property alias radius: hoverableButtonBackground.radius + + property bool isHovering: false + property bool isBeingPressed: false + + radius: height / 2 + font.pointSize: fontPointSize + font.kerning: true + hoverEnabled: true + + contentItem: Text { + text: hoverableButton.text + font: hoverableButton.font + opacity: enabled ? 1.0 : 0.3 + color: enabled? textColor : "grey" + horizontalAlignment: Text.AlignHCenter + verticalAlignment: Text.AlignVCenter + elide: Text.ElideRight + } + + background: Rectangle { + id: hoverableButtonBackground + color: backgroundColor + + MouseArea { + id: btnMouseArea + anchors.fill: hoverableButtonBackground + hoverEnabled: true + onPressed: { + hoverableButtonBackground.color = onPressColor + isBeingPressed = true + } + onReleased: { + hoverableButtonBackground.color = onReleaseColor + isBeingPressed = false + hoverableButton.clicked() + } + onEntered: { + hoverableButtonBackground.color = onEnterColor + isHovering = true + } + onExited: { + hoverableButtonBackground.color = onExitColor + isHovering = false + } + } + } + + LinearGradient { + id: backgroundGradient + + source: hoverableButtonBackground + anchors.fill: hoverableButtonBackground + start: Qt.point(0, 0) + end: Qt.point(width, 0) + gradient: Gradient { + GradientStop { position: 0.0; color: { + if(!hoverableButton.enabled){ + return backgroundColorDisabled + } + + if(isBeingPressed){ + return startColorPressed + } else { + if(isHovering){ + return startColorHovered + } else { + return startColor + } + } + } } + + GradientStop { position: 1.0; color: { + if(!hoverableButton.enabled){ + return backgroundColorDisabled + } + + if(isBeingPressed){ + return endColorPressed + } else { + if(isHovering){ + return endColorHovered + } else { + return endColor + } + } + } } + } + } +} diff --git a/src/wizardview/components/ImportFromBackupPage.qml b/src/wizardview/components/ImportFromBackupPage.qml new file mode 100644 index 00000000..bd7d26e2 --- /dev/null +++ b/src/wizardview/components/ImportFromBackupPage.qml @@ -0,0 +1,176 @@ +/* + * Copyright (C) 2020 by Savoir-faire Linux + * Author: Yang Wang + * + * 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 . + */ + +import QtQuick 2.14 +import QtQuick.Layouts 1.3 +import QtQuick.Controls 2.14 +import Qt.labs.platform 1.1 + +import "../../constant" +import "../../commoncomponents" + +ColumnLayout { + property alias text_passwordFromBackupEditAlias: passwordFromBackupEdit.text + property string fileImportBtnText: qsTr("Archive(none)") + + signal importFromFile_Dialog_Accepted(string fileDir) + + function clearAllTextFields() { + passwordFromBackupEdit.clear() + fileImportBtnText = qsTr("Archive(none)") + } + + JamiFileDialog { + id: importFromFile_Dialog + + mode: JamiFileDialog.OpenFile + title: qsTr("Open File") + folder: StandardPaths.writableLocation(StandardPaths.HomeLocation) + "/Desktop" + + nameFilters: [qsTr("Jami archive files") + " (*.gz)", qsTr( + "All files") + " (*)"] + + onAccepted: { + importFromFile_Dialog_Accepted(file) + } + } + + Layout.fillWidth: true + Layout.fillHeight: true + + Item { + Layout.alignment: Qt.AlignHCenter + Layout.fillWidth: true + Layout.fillHeight: true + } + + ColumnLayout { + Layout.alignment: Qt.AlignCenter + Layout.maximumWidth: 366 + + spacing: 12 + + RowLayout { + Layout.fillWidth: true + Layout.maximumHeight: 24 + spacing: 0 + + Item { + Layout.alignment: Qt.AlignVCenter + Layout.fillWidth: true + Layout.fillHeight: true + } + + Label { + id: importFromBackupLabel + Layout.minimumHeight: 24 + Layout.minimumWidth: 234 + text: qsTr("Import from backup") + font.pointSize: 13 + font.kerning: true + horizontalAlignment: Qt.AlignLeft + verticalAlignment: Qt.AlignVCenter + } + + HoverableRadiusButton { + id: backupInfoBtn + + buttonImageHeight: height + buttonImageWidth: width + + Layout.alignment: Qt.AlignVCenter + Layout.minimumWidth: 24 + Layout.preferredWidth: 24 + Layout.maximumWidth: 24 + + Layout.minimumHeight: 24 + Layout.preferredHeight: 24 + Layout.maximumHeight: 24 + + radius: height / 2 + icon.source: "/images/icons/info-24px.svg" + icon.height: 24 + icon.width: 24 + + backgroundColor: JamiTheme.releaseColor + onClicked: { + backupInfoLabel.visible = !backupInfoLabel.visible + } + } + Item { + Layout.alignment: Qt.AlignVCenter + Layout.fillWidth: true + Layout.fillHeight: true + } + } + + HoverableGradientButton { + id: fileImportBtn + + Layout.alignment: Qt.AlignHCenter + Layout.maximumWidth: 256 + Layout.preferredWidth: 256 + + Layout.maximumHeight: 30 + Layout.preferredHeight: 30 + Layout.minimumHeight: 30 + + text: fileImportBtnText + font.pointSize: 10 + font.kerning: true + + radius: height / 2 + backgroundColor: JamiTheme.releaseColor + + onClicked: { + importFromFile_Dialog.open() + } + } + + InfoLineEdit { + id: passwordFromBackupEdit + + Layout.alignment: Qt.AlignHCenter + + selectByMouse: true + echoMode: TextInput.Password + placeholderText: qsTr("Password") + } + + Label { + id: backupInfoLabel + + Layout.alignment: Qt.AlignHCenter + Layout.maximumWidth: 366 + Layout.preferredWidth: 366 + + text: qsTr("You can obtain an archive by clicking on \"Export account\" in the account settings. This will create a .gz file on your device.") + wrapMode: Text.WordWrap + horizontalAlignment: Text.AlignHCenter + verticalAlignment: Text.AlignVCenter + + visible: false + } + } + + Item { + Layout.alignment: Qt.AlignHCenter + Layout.fillWidth: true + Layout.fillHeight: true + } +} diff --git a/src/wizardview/components/ImportFromDevicePage.qml b/src/wizardview/components/ImportFromDevicePage.qml new file mode 100644 index 00000000..51816356 --- /dev/null +++ b/src/wizardview/components/ImportFromDevicePage.qml @@ -0,0 +1,142 @@ +/* + * Copyright (C) 2020 by Savoir-faire Linux + * Author: Yang Wang + * + * 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 . + */ + +import QtQuick 2.14 +import QtQuick.Layouts 1.3 +import QtQuick.Controls 2.14 + +import "../../constant" +import "../../commoncomponents" + +ColumnLayout { + property alias text_pinFromDeviceAlias: pinFromDevice.text + property alias text_passwordFromDeviceAlias: passwordFromDevice.text + + function initializeOnShowUp() { + clearAllTextFields() + } + + function clearAllTextFields() { + pinFromDevice.clear() + passwordFromDevice.clear() + } + + Layout.fillWidth: true + Layout.fillHeight: true + + Item { + Layout.alignment: Qt.AlignHCenter + Layout.preferredHeight: 40 + Layout.fillWidth: true + Layout.fillHeight: true + } + + ColumnLayout { + Layout.alignment: Qt.AlignCenter + Layout.fillWidth: true + + spacing: 12 + + RowLayout { + Layout.fillWidth: true + Layout.maximumHeight: 24 + spacing: 0 + + Item { + Layout.alignment: Qt.AlignVCenter + Layout.fillWidth: true + Layout.fillHeight: true + } + + Label { + id: importFromDeviceLabel + Layout.minimumHeight: 24 + Layout.minimumWidth: 234 + text: qsTr("Import from device") + font.pointSize: 13 + font.kerning: true + } + + HoverableRadiusButton { + id: pinInfoBtn + + buttonImageHeight: height + buttonImageWidth: width + + Layout.alignment: Qt.AlignVCenter + Layout.minimumWidth: 24 + Layout.maximumWidth: 24 + Layout.minimumHeight: 24 + Layout.maximumHeight: 24 + + radius: height / 2 + icon.source: "/images/icons/info-24px.svg" + backgroundColor: JamiTheme.releaseColor + + onClicked: { + pinInfoLabel.visible = !pinInfoLabel.visible + } + } + Item { + Layout.alignment: Qt.AlignVCenter + Layout.fillWidth: true + Layout.fillHeight: true + } + } + InfoLineEdit { + id: pinFromDevice + + Layout.alignment: Qt.AlignHCenter + + selectByMouse: true + placeholderText: qsTr("PIN") + } + + InfoLineEdit { + id: passwordFromDevice + + Layout.alignment: Qt.AlignHCenter + + selectByMouse: true + echoMode: TextInput.Password + placeholderText: qsTr("Password") + } + + Label { + id: pinInfoLabel + + Layout.alignment: Qt.AlignHCenter + Layout.minimumWidth: 256 + Layout.maximumWidth: 256 + + text: qsTr("To obtain a PIN (valid for 10 minutes), you need to open the account settings on the other device and click on \"Link to another device\".") + wrapMode: Text.WordWrap + horizontalAlignment: Text.AlignHCenter + verticalAlignment: Text.AlignVCenter + + visible: false + } + } + + Item { + Layout.alignment: Qt.AlignHCenter + Layout.preferredHeight: 40 + Layout.fillWidth: true + Layout.fillHeight: true + } +} diff --git a/src/wizardview/components/SpinnerPage.qml b/src/wizardview/components/SpinnerPage.qml new file mode 100644 index 00000000..2fb3f8d0 --- /dev/null +++ b/src/wizardview/components/SpinnerPage.qml @@ -0,0 +1,110 @@ +/* + * Copyright (C) 2020 by Savoir-faire Linux + * Author: Yang Wang + * + * 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 . + */ + +import QtQuick 2.14 +import QtQuick.Layouts 1.3 +import QtQuick.Controls 2.14 + +import "../../constant" + +ColumnLayout { + Layout.fillWidth: true + Layout.fillHeight: true + spacing: 6 + + property bool successState: true + property string progressLabelEditText: "Generating your Jami account" + + Item { + Layout.alignment: Qt.AlignHCenter + Layout.preferredHeight: 40 + Layout.fillWidth: true + Layout.fillHeight: true + } + Label { + id: spinnerLabel + Layout.alignment: Qt.AlignHCenter + Layout.minimumWidth: 200 + Layout.minimumHeight: 200 + + Layout.maximumWidth: 16777215 + Layout.maximumHeight: 16777215 + + property string spinnerDisplyState: successState ? "spinnerLabel_Regular" : "spinnerLabel_Failure" + onSpinnerDisplyStateChanged: { + switch (spinnerDisplyState) { + case "spinnerLabel_Regular": + background = Qt.createQmlObject("import QtQuick 2.14; +AnimatedImage { +source: \"qrc:/images/jami_eclipse_spinner.gif\" + +playing: true +paused: false +fillMode: Image.PreserveAspectFit +mipmap: true +}", spinnerLabel) + break + case "spinnerLabel_Failure": + background = Qt.createQmlObject("import QtQuick 2.14; +import \"qrc:/src/constant/\"; +Image { +anchors.fill: parent; +source:\"image://tintedPixmap/\" + (\"qrc:/images/icons/baseline-error_outline-24px.svg\").replace(\"qrc:/images/icons/\", \"\") + \"+\" + JamiTheme.urgentOrange_; +mipmap: true;}", spinnerLabel) + break + } + } + } + Item { + Layout.alignment: Qt.AlignHCenter + Layout.preferredHeight: 40 + Layout.fillWidth: true + Layout.fillHeight: true + } + Label { + id: progressLabel + Layout.alignment: Qt.AlignHCenter + text: successState ? progressLabelEditText : "Error creating account" + font.pointSize: 11 + font.kerning: true + + property string progressLabelState: successState ? "color_success" : "color_fail" + onProgressLabelStateChanged: { + switch (progressLabelState) { + case "color_success": + background = Qt.createQmlObject( + "import QtQuick 2.14; Rectangle { anchors.fill: parent; color: \"transparent\"; }", + progressLabel) + break + case "color_fail": + background = Qt.createQmlObject( + "import QtQuick 2.14; Rectangle { anchors.fill: parent; color: \"red\"; }", + progressLabel) + break + } + } + } + Item { + Layout.alignment: Qt.AlignHCenter + Layout.minimumHeight: 20 + Layout.maximumHeight: 20 + Layout.preferredHeight: 20 + Layout.fillWidth: true + Layout.fillHeight: false + } +} diff --git a/src/wizardview/components/WelcomePageLayout.qml b/src/wizardview/components/WelcomePageLayout.qml new file mode 100644 index 00000000..3c7190b0 --- /dev/null +++ b/src/wizardview/components/WelcomePageLayout.qml @@ -0,0 +1,238 @@ +/* + * Copyright (C) 2020 by Savoir-faire Linux + * Author: Yang Wang + * + * 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 . + */ + +import QtQuick 2.14 +import QtQuick.Layouts 1.3 +import QtQuick.Controls 2.14 + +import "../../constant" +import "../../commoncomponents" + +ColumnLayout { + property alias connectAccountManagerButtonAlias: connectAccountManagerButton + property alias newSIPAccountButtonAlias: newSIPAccountButton + + Layout.fillWidth: true + Layout.fillHeight: true + spacing: 6 + + signal welcomePageRedirectPage(int toPageIndex) + + Item { + // put a spacer to make the buttons closs to the middle + Layout.minimumHeight: 57 + Layout.maximumHeight: 57 + Layout.preferredHeight: 57 + Layout.fillWidth: true + } + RowLayout { + Layout.fillWidth: true + Layout.alignment: Qt.AlignHCenter + Label { + id: welcomeLabel + Layout.maximumHeight: 40 + Layout.alignment: Qt.AlignCenter + text: qsTr("Welcome to") + font.pointSize: 30 + font.kerning: true + } + } + Item { + Layout.minimumHeight: 17 + Layout.maximumHeight: 17 + Layout.preferredHeight: 17 + Layout.fillWidth: true + } + + RowLayout { + Layout.fillWidth: true + Layout.alignment: Qt.AlignHCenter + Label { + id: welcomeLogo + Layout.alignment: Qt.AlignCenter + Layout.minimumWidth: 100 + Layout.minimumHeight: 100 + Layout.maximumWidth: 16777215 + Layout.maximumHeight: 16777215 + Layout.preferredWidth: 300 + Layout.preferredHeight: 150 + color: "transparent" + background: Image { + id: logoIMG + source: "qrc:/images/logo-jami-standard-coul.png" + fillMode: Image.PreserveAspectFit + mipmap: true + } + } + } + Item { + // put a spacer to make the buttons closs to the middle + Layout.preferredHeight: 57 + Layout.fillWidth: true + Layout.fillHeight: true + } + RowLayout { + spacing: 6 + Layout.fillWidth: true + Layout.maximumHeight: 30 + Layout.alignment: Qt.AlignHCenter + HoverableGradientButton { + id: newAccountButton + + Layout.alignment: Qt.AlignCenter + Layout.preferredWidth: 256 + Layout.preferredHeight: 30 + text: qsTr("Create local account") + font.pointSize: 10 + font.kerning: true + radius: height / 2 + + onClicked: { + welcomePageRedirectPage(1) + } + } + } + RowLayout { + spacing: 6 + Layout.fillWidth: true + + Layout.maximumHeight: 30 + Layout.alignment: Qt.AlignHCenter + HoverableGradientButton { + id: fromDeviceButton + Layout.alignment: Qt.AlignCenter + Layout.preferredWidth: 256 + Layout.preferredHeight: 30 + text: qsTr("Import from device") + font.pointSize: 10 + font.kerning: true + + backgroundColor: JamiTheme.releaseColor + radius: height / 2 + + onClicked: { + welcomePageRedirectPage(5) + } + } + } + RowLayout { + spacing: 6 + Layout.fillWidth: true + + Layout.maximumHeight: 30 + Layout.alignment: Qt.AlignHCenter + HoverableGradientButton { + id: fromBackupButton + Layout.alignment: Qt.AlignCenter + Layout.preferredWidth: 256 + Layout.preferredHeight: 30 + text: qsTr("Import from backup") + font.pointSize: 10 + font.kerning: true + + backgroundColor: JamiTheme.releaseColor + radius: height / 2 + + onClicked: { + welcomePageRedirectPage(3) + } + } + } + RowLayout { + spacing: 6 + Layout.fillWidth: true + + Layout.maximumHeight: 30 + Layout.alignment: Qt.AlignHCenter + Button { + id: showAdvancedButton + Layout.preferredWidth: 256 + Layout.preferredHeight: 30 + Layout.alignment: Qt.AlignCenter + text: qsTr("Show Advanced") + font.pointSize: 8 + font.kerning: true + + background: Rectangle{ + anchors.fill: parent + + color: "transparent" + radius: height /2 + } + + onClicked: { + connectAccountManagerButton.visible = !connectAccountManagerButton.visible + newSIPAccountButton.visible = !newSIPAccountButton.visible + } + } + } + RowLayout { + spacing: 6 + Layout.fillWidth: true + Layout.alignment: Qt.AlignHCenter + + Layout.maximumHeight: 30 + HoverableGradientButton { + id: connectAccountManagerButton + Layout.preferredWidth: 256 + Layout.preferredHeight: 30 + Layout.alignment: Qt.AlignCenter + text: qsTr("Connect to account manager") + visible: false + font.pointSize: 10 + font.kerning: true + + backgroundColor: JamiTheme.releaseColor + radius: height / 2 + + onClicked: { + welcomePageRedirectPage(6) + } + } + } + RowLayout { + spacing: 6 + Layout.fillWidth: true + Layout.alignment: Qt.AlignHCenter + Layout.maximumHeight: 30 + + HoverableGradientButton { + id: newSIPAccountButton + Layout.preferredWidth: 256 + Layout.preferredHeight: 30 + Layout.alignment: Qt.AlignCenter + text: qsTr("Add a new SIP account") + visible: false + font.pointSize: 10 + font.kerning: true + + radius: height / 2 + backgroundColor: JamiTheme.releaseColor + + onClicked: { + welcomePageRedirectPage(2) + } + } + } + Item { + // put a spacer to make the buttons closs to the middle + Layout.fillHeight: true + Layout.preferredHeight: 65 + Layout.fillWidth: true + } +} diff --git a/stylesheet.css b/stylesheet.css new file mode 100644 index 00000000..c4f8198f --- /dev/null +++ b/stylesheet.css @@ -0,0 +1,963 @@ +QToolTip { + color: white; + background-color: #109ede; + border: 1px solid white; +} + +QPushButton { + background-color: rgb(242, 242, 242); + border-style: solid; + border-width: 0px; + border-radius: 15px; + color: rgb(32, 32, 32); +} + +QPushButton#pinInfoBtn, QPushButton#backupInfoBtn { + background: transparent; +} + +QPushButton#takePhotoButton, QPushButton#importButton { + background-color: rgb(242, 242, 242); + border-radius: 5px; + border:solid 0px; +} + +QPushButton#acceptButton{ + background-color: #4caf50; + border-radius: 28px; + border:solid 1px; +} + +QPushButton#refuseButton, QPushButton#cancelButton{ + background-color: #f44336; + border-radius: 28px; + border:solid 1px; +} + +QPushButton#acceptButton:hover{ + background-color: #5db761; +} + +QPushButton#acceptButton:pressed{ + background-color: #449d48; +} + +QPushButton#refuseButton:hover, QPushButton#cancelButton:hover{ + background-color: #f5554a; +} + +QPushButton#refuseButton:pressed, QPushButton#cancelButton:pressed{ + background-color: #db3c30; +} + +QWidget#smartListOuterWidget { + background-color: rgb(255, 255, 255); +} + +QWidget#previewContainer { + background-color: black; +} + +QPushButton#btnConversations, QPushButton#btnInvites { + border-radius: 0px; + border-top-left-radius: 15px; + border-top-right-radius: 15px; + color: rgb(32, 32, 32); + height: 28px; + padding: 0px; + background-color: rgb(240, 240, 240); + border-top: 2px solid rgb(240, 240, 240); + border-right: 2px solid rgb(240, 240, 240); + border-bottom: 2px solid rgb(240, 240, 240); + border-left: 2px solid rgb(240, 240, 240); +} + +QPushButton#btnConversations:hover, QPushButton#btnInvites:hover { + background-color: rgb(188, 185, 184); + border-top: 2px solid rgb(188, 185, 184); + border-right: 2px solid rgb(188, 185, 184); + border-bottom: 2px solid rgb(188, 185, 184); + border-left: 2px solid rgb(188, 185, 184); +} + +QPushButton#btnConversations:checked, QPushButton#btnInvites:checked { + background-color: rgb(255, 255, 255); + border-bottom: 2px solid rgb(255, 255, 255); +} + +QPushButton#btnConversations:hover:checked, QPushButton#btnInvites:hover:checked { + border-top: 2px solid rgb(240, 240, 240); + border-right: 2px solid rgb(240, 240, 240); + border-bottom: 2px solid rgb(255, 255, 255); + border-left: 2px solid rgb(240, 240, 240); +} + +QPushButton#imBackButton, QPushButton#btnAcceptInvite, QPushButton#btnIgnoreInvite, +QPushButton#btnBlockInvite, QPushButton#btnAudioCall, QPushButton#btnVideoCall, +QPushButton#sendContactRequestButton, QPushButton#sendButton, QPushButton#sendIMButton, +QPushButton#btnExitSettings { + background-color: transparent; + border-style: solid; + border-width: 0px; + border-radius: 15px; + padding: 8px; + color: rgb(32, 32, 32); +} + +QPushButton#btnAcceptInvite:hover, QPushButton#btnIgnoreInvite:hover, QPushButton#btnBlockInvite:hover { + background-color: rgb(212, 212, 212); +} + +QPushButton#btnAcceptInvite:pressed, QPushButton#btnIgnoreInvite:pressed, QPushButton#btnBlockInvite:pressed { + background-color: rgb(187, 187, 187); +} + + QPushButton#imBackButton:hover, QPushButton#btnAudioCall:hover, QPushButton#btnVideoCall:hover, + QPushButton#sendContactRequestButton:hover, QPushButton#sendButton:hover, QPushButton#sendIMButton:hover, + QPushButton#btnExitSettings:hover, QPushButton#btnDeleteAccept:hover, QPushButton#btnDeleteCancel:hover, + QPushButton#changelogButton:hover, QPushButton#creditsButton:hover, QPushButton#changelogButton:hover, QPushButton#updateCancelBtn:hover, + QPushButton#updateAcceptBtn:hover, QPushButton#installBetaButton:hover, QPushButton#closeAboutDialogButton:hover { + background-color: rgb(237, 237, 237); + } + + QPushButton#imBackButton:pressed, QPushButton#btnAudioCall:pressed, QPushButton#btnVideoCall:pressed, + QPushButton#sendContactRequestButton:pressed, QPushButton#sendButton:pressed, QPushButton#sendIMButton:pressed, + QPushButton#btnExitSettings:pressed, QPushButton#btnDeleteAccept:pressed, QPushButton#btnDeleteCancel:pressed, + QPushButton#changelogButton:pressed, QPushButton#creditsButton:pressed, QPushButton#changelogButton:pressed, QPushButton#updateCancelBtn:pressed, + QPushButton#updateAcceptBtn:pressed, QPushButton#installBetaButton:pressed, QPushButton#closeAboutDialogButton:pressed { + background-color: rgb(212, 212, 212); + } + +QWidget#searchBarLayoutWidget, QWidget#smartList, +QWidget#sidePanelLayoutWidget, QWidget#leftSettingsWidget { + border-right: 2px solid rgb(240, 240, 240); +} + +RingContactLineEdit{ + border-radius: 15px; + border: 2px solid rgb(240, 240, 240); + background-color: rgb(240, 240, 240); +} + +RingContactLineEdit:focus{ + border: 2px solid rgb(240, 240, 240); + background-color: rgb(255, 255, 255); +} + +.QLineEdit{ + border-color: rgb(240, 240, 240); + border-radius: 15px; + border-width: 2px; + background-color: rgb(240, 240, 240); + padding-left: 4px; + padding-right: 4px; + height: 30px; +} + +QScrollBar:vertical { + border: none; + background: white; + width: 0px; +} + +QScrollBar::handle:vertical { + background: white; + max-width: 0px; +} + +QScrollBar:horizontal { + border: 2px solid grey; + background: grey; + height: 10px; +} + +QScrollBar::handle:horizontal { + background: white; + min-width: 20px; + border-radius: 10px; +} + +QScrollBar::add-line:horizontal { + height: 0px; +} + +QScrollBar::sub-line:horizontal { + height: 0px; +} + +QScrollBar::add-page:horizontal, QScrollBar::sub-page:horizontal { + height: 0px; +} + +SmartListView { + background-color: white; + border: none; +} + +SmartListView::item:selected, QListView#BannedList::item:selected { + background-color: rgba(220, 220, 220, 255); + border: none; +} + +SmartListView::item:hover, QListView#BannedList::item:hover { + background-color: rgba(242, 242, 242, 255); +} + +QWidget#messagingHeaderWidget { + background-color: rgba(255, 255, 255, 255); + border-bottom: 2px solid rgb(240, 240, 240); +} + +QWidget#messageViewLayoutWidget, QWidget#welcomePage { + background-color: rgba(255, 255, 255, 255); +} + +QWidget#newWizardWidgetScrollAreaContents, QWidget#settingsWidgetScrollAreaContents { + background-color: rgba(255, 255, 255, 255); + border: none; +} + +QScrollArea#newWizardWidgetScrollArea, QScrollArea#settingsWidgetScrollArea { + border: none; +} + +QPushButton#holdButton, QPushButton#chatButton, QPushButton#noMicButton, QPushButton#noVideoButton, QPushButton#hangupButton, +QPushButton#transferButton, QPushButton#addPersonButton, QPushButton#joinButton, +QPushButton#qualityButton, QPushButton#recButton, QPushButton#transferCallButton, +QPushButton#sipInputPanelButton, QPushButton#addToConferenceButton { + background-color: transparent; + border-radius: 18px; + border: solid 1px; +} + + QPushButton#holdButton:hover, QPushButton#chatButton:hover, QPushButton#noMicButton:hover, QPushButton#hangupButton:hover, + QPushButton#noVideoButton:hover, QPushButton#transferButton:hover, QPushButton#addPersonButton:hover, + QPushButton#joinButton:hover, QPushButton#qualityButton:hover, QPushButton#addToContactButton:hover, + QPushButton#recButton:hover, QPushButton#transferCallButton:hover, + QPushButton#sipInputPanelButton:hover, QPushButton#addToConferenceButton:hover { + background-color: transparent; + border-radius: 18px; + border: solid 1px; + } + + QPushButton#holdButton:pressed, QPushButton#chatButton:pressed, QPushButton#noMicButton:pressed, QPushButton#hangupButton:pressed, + QPushButton#noVideoButton:pressed, QPushButton#transferButton:pressed, QPushButton#addPersonButton:pressed, + QPushButton#joinButton:pressed, QPushButton#qualityButton:pressed, QPushButton#addToContactButton:pressed, + QPushButton#recButton:pressed, QPushButton#addToConferenceButton:pressed { + background-color: transparent; + border-radius: 18px; + border: solid 1px; + } + + QPushButton#holdButton:checked, QPushButton#noMicButton:checked, QPushButton#hangupButton:checked, + QPushButton#noVideoButton:checked, QPushButton#recButton:checked, + QPushButton#chatButton:checked, QPushButton#transferCallButton:checked, + QPushButton#sipInputPanelButton:checked, QPushButton#addToConferenceButton:checked { + background-color: transparent; + border-radius: 18px; + border: solid 1px; + } + +QPushButton#updateCancelButton { + padding: 4px; + background: #369; + color: white; + font-size: 12px; + border: 0; + border-radius: 3px; + outline: 0px; + width: 50px; +} + +QPushButton#updateCancelButton:hover { + background: #47a; +} + +QPushButton#updateCancelButton:pressed { + background: #58b; +} + +QMessageBox QPushButton { + padding: 4px; + background: #369; + color: white; + font-size: 12px; + border: 0; + border-radius: 3px; + outline: 0px; + width: 50px; +} + +QMessageBox QPushButton:hover { + background: #47a; +} + +QMessageBox QPushButton:pressed { + background: #58b; +} + +QToolButton#qrButton, QToolButton#shareButton { + background-color: rgb(242, 242, 242); + border-style: solid; + border-width: 0px; + border-radius: 15px; + padding: 8px; + color: rgb(32, 32, 32); +} + + QToolButton#qrButton:hover, QToolButton#shareButton:hover { + background-color: rgb(237, 237, 237); + } + + QToolButton#qrButton:pressed, QToolButton#shareButton:pressed { + background-color: rgb(212, 212, 212); + } + +QToolButton#qrButton:checked { + background-color: rgb(237, 237, 237); +} + +QPushButton#btnvideo{ + background-color: #109ede; + border-radius: 15px; + border:solid 1px; +} + +QWidget#messagingPage, QWidget#contactRequestPage, +QDialog#DeleteAccountDialog, QDialog#UpdateDownloadDialog, +QDialog#UpdateConfirmDialog, QDialog#AccountMigrationDialog { + background: rgb(255, 255, 255); +} + +QWidget#messagingPage { + background: rgb(255, 255, 255); +} + +QDialog#PasswordDialog, +QDialog#LinkDeviceDialog, +QDialog#DeleteAccountDialog { + background: rgb(255, 255, 255); +} + +QPushButton#deleteAccountPushButton { + background-color: red; + border: 0px; + border-radius: 15px; + height: 30px; + color: white; +} + +QPushButton#deleteAccountPushButton:hover { + background-color: rgb(230, 0, 0); +} + +QPushButton#deleteAccountPushButton:disabled { + background-color: rgba(255, 0, 0, 0.8); +} + +QPushButton#nextButton, QPushButton#playButton, QPushButton#clearHistoryButton, QPushButton#doTransferButton, +QPushButton#photoButton, QPushButton#migrationPushButton, +QPushButton#fromDeviceButton, QPushButton#newAccountButton, QPushButton#previousButton, QPushButton#exportButton, QPushButton#newSIPAccountButton, QPushButton#fromBackupButton, QPushButton#connectAccountManagerButton, +QPushButton#cancelAddButton, QPushButton#exportOnRingButton, QPushButton#addDeviceButton, QPushButton#exportEndedOkButton, +QPushButton#errorPushButton, QPushButton#registerButton, QPushButton#acceptCRButton, QPushButton#discardCRButton, QPushButton#deleteCancelBtn, +QPushButton#skipBtn, QPushButton#exportBtn, +QPushButton#dhtImportBtn, QPushButton#fileImportBtn, QPushButton#changePassBtn, QPushButton#confirmChangeBtn, QPushButton#backButton { + background: qlineargradient(x1: 0, y1: 0, x2: 1, y2: 0, stop: 0 #109ede, stop: 1.0 #2b5084); + border: 0px; + border-radius: 15px; + height: 30px; + color: white; +} + +QPushButton#nextButton:disabled, QPushButton#playButton:disabled, QPushButton#clearHistoryButton:disabled, +QPushButton#doTransferButton:disabled, QPushButton#photoButton:disabled, QPushButton#fromBackupButton:disabled +QPushButton#existingPushButton:disabled, QPushButton#newAccountButton:disabled, QPushButton#previousButton:disabled, QPushButton#newSIPAccountButton:disabled, +QPushButton#exportButton:disabled, QPushButton#cancelAddButton:disabled, QPushButton#exportOnRingButton:disabled, +QPushButton#addDeviceButton:disabled, QPushButton#exportEndedOkButton:disabled, QPushButton#errorPushButton:disabled, +QPushButton#registerButton:disabled, QPushButton#acceptCRButton:disabled, QPushButton#discardCRButton:disabled, +QPushButton#deleteCancelBtn:disabled, QPushButton#dhtImportBtn:disabled, QPushButton#fileImportBtn:disabled, +QPushButton#changePassBtn:disabled, QPushButton#confirmChangeBtn:disabled, QPushButton#backButton:disabled, +QPushButton#fromDeviceButton:disabled, QPushButton#connectAccountManagerButton:disabled, QPushButton#exportBtn:disabled, +QPushButton#skipBtn:disabled, QPushButton#migrationPushButton:disabled { + background: rgba(242, 242, 242, 0.8); + color: grey; +} + +QPushButton#blockCRButton, QPushButton#debanButton, QPushButton#deleteBanBtn, +QPushButton#cancelChangeBtn { + background-color: rgb(251, 72, 71); + border: 0px; + color: white; +} + +QPushButton#nextButton:hover, QPushButton#playButton:hover, QPushButton#clearHistoryButton:hover, +QPushButton#doTransferButton:hover, QPushButton#photoButton:hover, QPushButton#fromBackupButton:hover, +QPushButton#existingPushButton:hover, QPushButton#newAccountButton:hover, QPushButton#previousButton:hover, QPushButton#newSIPAccountButton:hover, +QPushButton#exportButton:hover, QPushButton#cancelAddButton:hover, QPushButton#exportOnRingButton:hover, +QPushButton#addDeviceButton:hover, QPushButton#exportEndedOkButton:hover, QPushButton#errorPushButton:hover, +QPushButton#registerButton:hover, QPushButton#acceptCRButton:hover, QPushButton#discardCRButton:hover, +QPushButton#deleteCancelBtn:hover, QPushButton#dhtImportBtn:hover, QPushButton#fileImportBtn:hover, QPushButton#migrationPushButton:hover, +QPushButton#changePassBtn:hover, QPushButton#confirmChangeBtn:hover, QPushButton#backButton:hover, QPushButton#skipBtn:hover, +QPushButton#fromDeviceButton:hover, QPushButton#connectAccountManagerButton:hover, QPushButton#exportBtn:hover { + background: qlineargradient(x1: 0, y1: 0, x2: 1, y2: 0, stop: 0 #2b4b7e, stop: 1.0 #001d4d); + color: white; +} + +QPushButton#blockCRButton:hover, QPushButton#deleteAcceptBtn:hover, QPushButton#debanButton:hover, +QPushButton#deleteButton:hover, QPushButton#deleteBanBtn:hover, QPushButton#cancelChangeBtn:hover { + background-color: rgb(252, 91, 90); +} + +QPushButton#nextButton:pressed, QPushButton#playButton:pressed, QPushButton#clearHistoryButton:pressed, +QPushButton#doTransferButton:pressed, QPushButton#photoButton:pressed, QPushButton#skipBtn:pressed, QPushButton#migrationPushButton:pressed, +QPushButton#existingPushButton:pressed, QPushButton#newAccountButton:pressed, QPushButton#previousButton:pressed, QPushButton#newSIPAccountButton:pressed, +QPushButton#exportButton:pressed, QPushButton#cancelAddButton:pressed, QPushButton#exportOnRingButton:pressed, +QPushButton#addDeviceButton:pressed, QPushButton#exportEndedOkButton:pressed, QPushButton#errorPushButton:pressed, +QPushButton#registerButton:pressed, QPushButton#acceptCRButton:pressed, QPushButton#discardCRButton:pressed, +QPushButton#deleteCancelBtn:pressed, QPushButton#dhtImportBtn:pressed, QPushButton#fileImportBtn:pressed, +QPushButton#changePassBtn:pressed, QPushButton#confirmChangeBtn:pressed, QPushButton#backButton:pressed, QPushButton#exportBtn:pressed { + background: qlineargradient(x1: 0, y1: 0, x2: 1, y2: 0, stop: 0 #043161, stop: 1.0 #00113f); + color: white; +} + +QPushButton#blockCRButton:pressed, QPushButton#deleteAcceptBtn:pressed, QPushButton#debanButton:pressed, +QPushButton#deleteBanBtn:pressed, QPushButton#cancelChangeBtn:pressed{ + background-color: rgb(219, 55, 54); +} + +QPushButton#btnChangePasswordCancel { + background-color: rgb(252, 91, 90); + color: white; +} + +QPushButton#btnChangePasswordCancel:hover { + background-color: red; + color: white; +} + +QPushButton#btnChangePasswordCancel:pressed { + background-color: darkred; + color: white; +} + +QComboBox{ + background: transparent; + border-radius: 0px; + border-style: solid; + border-width: 2px; + border-color: #414141; + border-bottom: transparent; + border-top: transparent; + border-left: transparent; + border-right: transparent; + font-family: "Sans Serif"; + padding: 2px; +} + +QComboBox::down-arrow{ + border-radius: 0px; + border-style: solid; + border-width: 2px; + height: 36; + width : 36; + image: url(":/images/icons/ic_arrow_drop_down_black_18dp_2x.png"); +} + +QComboBox::drop-down{ + border: 0; + width: 36px; +} + +QRadioButton::indicator{ + width: 1 ; + height: 12px; + border-radius: 8px; + border-width: 2px; + border-style: solid; +} + +QRadioButton::indicator:unchecked{ + border-color: rgb(77, 77, 77); + background: transparent; +} + +QRadioButton::indicator:checked{ + background: #109ede; + border-color: #109ede; + image: url(":/images/icons/ic_check_white_18dp_2x.png"); +} + +QWidget#horizontalWidget{ + background: transparent; +} + +QCheckBox::indicator{ + height : 12 px; + width : 12 px; + border: 2px solid rgb(77, 77, 77); + border-radius: 4px; + background: none; +} + +QCheckBox::indicator:checked{ + border-color: #2b4b7e; + background: #2b4b7e; + image: url(":/images/icons/ic_check_white_18dp_2x.png"); +} + +QSpinBox::down-button{ + height: 9; + width : 9; + image: url(":/images/icons/ic_arrow_drop_down_black_9dp_2x.png"); +} + +QSpinBox::up-button{ + height: 9; + width : 9; + image: url(":/images/icons/ic_arrow_drop_up_black_9dp_2x.png"); +} + +QLineEdit#lrcfg_alias:focus, QLineEdit#lrcfg_hostname:focus, QLineEdit#lrcfg_password:focus, +QLineEdit#lrcfg_proxy:focus, QLineEdit#lrcfg_mailbox:focus, QLineEdit#lrcfg_tlsPassword:focus, +QLineEdit#lrcfg_tlsServerName:focus, QLineEdit#lrcfg_turnServerRealm:focus, QLineEdit#lrcfg_turnServerUsername:focus, +QLineEdit#lrcfg_turnServerPassword:focus, QLineEdit#lrcfg_turnServer:focus, QLineEdit#lrcfg_publishedAddress:focus, +QLineEdit#lrcfg_registeredName:focus, QLineEdit#lrcfg_nameServiceURL:focus, QLineEdit#lrcfg_username:focus, +QLineEdit#profileNameEdit:focus{ + border-color: #109ede; +} + +QTabWidget#tabWidget{ + border-color: transparent; +} + +QPushButton#upAudioButton, QPushButton#downAudioButton, QPushButton#upVideoButton, QPushButton#downVideoButton{ + background: transparent; +} + +QPushButton#avatarButton:hover { + border: 2px solid rgb(77, 77, 77); + border-radius: 50px; +} + +QWidget#leftPannel{ + background: white; +} + +QSlider::groove:vertical{ + background: red; + position: absolute; /* absolutely position 4px from the left and right of the widget. setting margins on the widget should work too... */ + width:2px; +} + +QSlider::handle:vertical{ + height: 10px; + background: #109ede; + border-radius: 5px; + margin: 0 -4px; +} + +QSlider::sub-page:vertical{ + background: #777777; +} + +QSlider::add-page:vertical{ + background: #109ede; +} + +QToolButton::menu-button {image:none;} + +QToolButton::menu-arrow {image:none;} + +QLabel#accountIdLabel, QLabel#accountAliasLabel, QLabel#deletionLabel1, QLabel#deletionLabel2, +QLabel#warningLabel{ + background: transparent; +} + +QLabel#accountAliasLabel, QLabel#deletionLabel1, QLabel#deletionLabel2{ + color: black; +} + +QLabel#warningLabel{ + color: red; +} + +QLabel#labelWarning { + color: darkorange; +} + +QLabel#accountIdLabel{ + color: LightSlateGrey; + font-style: italic; +} + +QLabel#accountAliasLabel{ + font-weight: bold; +} + +QLabel#dragDropLabel { + /*rgba 0.95 opacity (transparency)*/ + font-size: 20px; + border: 2px dashed black; + border-radius: 10px; + background: rgba(216, 234, 252, 0.95); +} + +QLabel#wrongPasswordLabel { + color: red; + margin-left: 8px; +} + +/* setAvatarDialog { */ +QPushButton#pictureButton:default, QPushButton#fileButton:default { + background-color: rgb(0, 192, 213,); +} + +QPushButton#pictureButton:checked, QPushButton#fileButton:checked { + background-color: rgb(0, 0, 213); +} +/* } setAvatarDialog */ + +QSpinBox { + background-color: rgb(240, 240, 240); + border-radius: 14px; + height: 28px; + padding: 2px; + margin-bottom: 4px; +} + +QSpinBox::up-button { + subcontrol-origin: border; + subcontrol-position: top right; + width: 16px; + height: 18px; + padding-right: 4px; + margin-top: 3px; +} + +QSpinBox::down-button { + subcontrol-origin: border; + subcontrol-position: bottom right; + width: 16px; + height: 18px; + padding-right: 4px; + margin-bottom: 3px; +} + +/* SettingsWidget { */ +SettingsWidget QLabel#exportedPIN { + color: darkblue; + margin-bottom: 4px; +} + +SettingsWidget QPushButton { + padding-right: 16px; + padding-left: 16px; + border-style: solid; + border-width: 0px; + border-radius: 15px; + color: rgb(32, 32, 32); + background-color: rgb(242, 242, 242); +} + +SettingsWidget QPushButton:hover { + background-color: rgb(237, 237, 237); +} + +SettingsWidget QPushButton:pressed { + background-color: rgb(212, 212, 212); +} + +SettingsWidget QPushButton:disabled { + color: gray; +} + +SettingsWidget QLabel:disabled { + color: rgb(160, 160, 160); +} + +SettingsWidget QWidget#leftSettingsWidget, +SettingsWidget QWidget#rightSettingsWidget, +SettingsWidget QWidget#DeleteAccountDialog, +SettingsWidget QWidget#advancedSettingsWidget, +SettingsWidget QWidget#advancedSIPSettingsWidget, +SettingsWidget QWidget#NameRegistrationDialog, +SettingsWidget QWidget#centralWidget, +SettingsWidget QWidget#centralSIPWidget, +SettingsWidget QWidget#scrollAreaWidgetContents, +SettingsWidget QWidget#scrollAreaSIPWidgetContents { + background-color: rgba(255, 255, 255, 255); +} + +SettingsWidget .QLineEdit { + border-radius: 15px; + background-color: rgb(240, 240, 240); + padding-left: 8px; + padding-right: 8px; + height: 30px; +} + +SettingsWidget QLineEdit#currentRingID { + border: 0px; + border-radius: 0px; + padding: 0px; + background-color: transparent; + font-weight: bold; +} + +SettingsWidget QLineEdit#currentRegisteredID { + border: 2px; + border-radius: 15px; + padding: 1px; + padding-left: 8px; + margin-right: 4px; + border-style: solid; + background-color: rgb(240, 240, 240); +} + +SettingsWidget QPushButton#regNameButton { + background-color: transparent; +} + +SettingsWidget QWidget#videoLayoutWidget { + background-color: black; +} + +SettingsWidget QPushButton#btnDeletAccount, +SettingsWidget QPushButton#btnSIPDeletAccount { + background-color: rgb(252, 91, 90); + color: white; +} + +SettingsWidget QPushButton#btnDeletAccount:hover, +SettingsWidget QPushButton#btnSIPDeletAccount:hover { + background-color: red; + color: white; +} + +SettingsWidget QPushButton#btnDeletAccount:pressed, +SettingsWidget QPushButton#btnSIPDeletAccount:pressed { + background-color: darkred; + color: white; +} + +QListView .QLabel#labelDeviceId { + padding-left: 4px; + font-weight: 300; +} + +QListView .QLabel#labelThisDevice { + margin-right: 16px; + font-style: italic; + color: green; +} + +QListWidget .QLabel { + background-color: transparent; +} + +QListWidget .QLineEdit { + background-color: transparent; +} + +QListWidget .QPushButton { + background-color: transparent; +} + QListWidget .QPushButton:hover { + background-color: transparent; + } + QListWidget .QPushButton:pressed { + background-color: transparent; + } + +QListView::item:selected { + background-color: rgb(220, 220, 220); +} + +SettingsWidget QListView { + background-color: whitesmoke; + border: 1px solid rgb(212, 212, 212); + font-size: 16px; +} + +SettingsWidget QListView::item { + height: 30px; + font: 30px; + padding: 8px; +} + +SettingsWidget QListView::indicator { + height: 12 px; + width: 12 px; + border: 2px solid rgb(77, 77, 77); + border-radius: 4px; + background: none; +} + +SettingsWidget QListView::indicator:checked { + border-color: #2b4b7e; + background: #2b4b7e; + image: url(":/images/icons/ic_check_white_18dp_2x.png"); +} + +SettingsWidget QListView::item:selected { + background-color: rgba(220, 220, 220, 255); + border: none; + color: black; +} + +SettingsWidget QListView::item:hover { + background-color: rgba(229, 229, 229, 255); +} + +SettingsWidget QListView::item:disabled { + background-color: transparent; +} + +/* } SettingsWidget */ + +QPushButton#panelButton_0, QPushButton#panelButton_1, QPushButton#panelButton_2, +QPushButton#panelButton_3, QPushButton#panelButton_4, QPushButton#panelButton_5, +QPushButton#panelButton_6, QPushButton#panelButton_7, QPushButton#panelButton_8, +QPushButton#panelButton_9, QPushButton#panelButton_hash, QPushButton#panelButton_A, +QPushButton#panelButton_B, QPushButton#panelButton_C, QPushButton#panelButton_D { + text-align: center; + text-decoration: none; + background: #369; + color: white; + border: 0; + border-radius: 19px; + padding-bottom: 4px; +} + +QPushButton#panelButton_star { + text-align: center; + text-decoration: none; + background: #369; + color: white; + border: 0; + border-radius: 19px; + padding-top: 4px; +} + +QPushButton#panelButton_0:hover, QPushButton#panelButton_1:hover, QPushButton#panelButton_2:hover, +QPushButton#panelButton_3:hover, QPushButton#panelButton_4:hover, QPushButton#panelButton_5:hover, +QPushButton#panelButton_6:hover, QPushButton#panelButton_7:hover, QPushButton#panelButton_8:hover, +QPushButton#panelButton_9:hover, QPushButton#panelButton_hash:hover, QPushButton#panelButton_star:hover, +QPushButton#panelButton_A:hover, QPushButton#panelButton_B:hover, QPushButton#panelButton_C:hover, +QPushButton#panelButton_D:hover { + background: #47a; +} + +QPushButton#panelButton_0:pressed, QPushButton#panelButton_1:pressed, QPushButton#panelButton_2:pressed, +QPushButton#panelButton_3:pressed, QPushButton#panelButton_4:pressed, QPushButton#panelButton_5:pressed, +QPushButton#panelButton_6:pressed, QPushButton#panelButton_7:pressed, QPushButton#panelButton_8:pressed, +QPushButton#panelButton_9:pressed, QPushButton#panelButton_hash:pressed, QPushButton#panelButton_star:pressed, +QPushButton#panelButton_A:pressed, QPushButton#panelButton_B:pressed, QPushButton#panelButton_C:pressed, +QPushButton#panelButton_D:pressed { + background: #58b; +} + +QProgressBar#audioInputMeter { + border: 0px solid #606060; + background: lightgrey; +} + + QProgressBar#audioInputMeter::chunk { + background-color: #0c79aa; + margin: 2px; + } + +QLabel#nameLabel { + font-size: 20px; + font-style: initial; + qproperty-alignment: AlignCenter; + color: white; +} + +QWidget#videoPage { + background: black; +} + +QPushButton#recordOverlayStartOrFinishRecordingBtn, QPushButton#recordOverlayDeleteBtn, QPushButton#recordOverlayPlayBtn, QPushButton#recordOverlayRerecordBtn, QPushButton#recordOverlaySendBtn, +QPushButton#recordOverlayStopPlayingBtn { + background-color: transparent; + border-radius: 18px; + border: solid 1px; +} + +QPushButton#recordOverlayStartOrFinishRecordingBtn:hover, QPushButton#recordOverlayDeleteBtn:hover, QPushButton#recordOverlayPlayBtn:hover, QPushButton#recordOverlayRerecordBtn:hover, QPushButton#recordOverlaySendBtn:hover, +QPushButton#recordOverlayStopPlayingBtn:hover { + background-color: transparent; + border-radius: 18px; + border: solid 1px; +} + +QPushButton#recordOverlayStartOrFinishRecordingBtn:pressed, QPushButton#recordOverlayDeleteBtn:pressed, QPushButton#recordOverlayPlayBtn:pressed, QPushButton#recordOverlayRerecordBtn:pressed, QPushButton#recordOverlaySendBtn:pressed, +QPushButton#recordOverlayStopPlayingBtn:pressed { + background-color: transparent; + border-radius: 18px; + border: solid 1px; +} + +QPushButton#recordOverlayStartOrFinishRecordingBtn:checked, QPushButton#recordOverlayDeleteBtn:checked, QPushButton#recordOverlayPlayBtn:checked, QPushButton#recordOverlayRerecordBtn:checked, QPushButton#recordOverlaySendBtn:checked, +QPushButton#recordOverlayStopPlayingBtn:checked { + background-color: transparent; + border-radius: 18px; + border: solid 1px; +} + +QWidget#RecordWidget { + background-color: transparent; +} + +QLabel#timerLabel { + background-color: transparent; + color: white; +} + +QProgressBar#levelMeter { + border: 2px solid white; + text-align: center; + background: transparent; +} + + QProgressBar#levelMeter::chunk { + background-color: white; + margin: 2px; + } + +QScrollArea#changeLogScrollArea { + background-color: transparent; + color: white; + border: none; +} + +QWidget#changeLogContents { + background-color: transparent; + color: white; + border: none; +} + +QTextEdit#logTextEdit { + background-color: white; + color: black; +} + +QPushButton#logCloseButton { + background-color: rgb(189, 189, 189); +} + + QPushButton#logCloseButton:hover { + background-color: rgb(170, 170, 170); + } + QPushButton#logCloseButton:pressed { + background-color: rgb(180, 180, 180); + } + +FullScreenNotification { + font-size: 24px; + color: white; + background-color: black; + border: 2px solid white; + padding: 100px; +} \ No newline at end of file diff --git a/stylesheet.linux.css b/stylesheet.linux.css new file mode 100644 index 00000000..44eeecf5 --- /dev/null +++ b/stylesheet.linux.css @@ -0,0 +1,930 @@ + +QPushButton { + background-color: rgb(242, 242, 242); + border-style: solid; + border-width: 0px; + border-radius: 15px; + color: rgb(32, 32, 32); +} + +QPushButton#pinInfoBtn, QPushButton#backupInfoBtn { + background: transparent; +} + +QPushButton#takePhotoButton, QPushButton#importButton { + background-color: rgb(242, 242, 242); + border-radius: 5px; + border:solid 0px; +} + +QPushButton#acceptButton{ + background-color: #4caf50; + border-radius: 28px; + border:solid 1px; +} + +QPushButton#refuseButton, QPushButton#cancelButton{ + background-color: #f44336; + border-radius: 28px; + border:solid 1px; +} + +QPushButton#acceptButton:hover{ + background-color: #5db761; +} + +QPushButton#acceptButton:pressed{ + background-color: #449d48; +} + +QPushButton#refuseButton:hover, QPushButton#cancelButton:hover{ + background-color: #f5554a; +} + +QPushButton#refuseButton:pressed, QPushButton#cancelButton:pressed{ + background-color: #db3c30; +} + +QWidget#smartListOuterWidget { + background-color: rgb(255, 255, 255); +} + +QWidget#previewContainer { + background-color: black; +} + +QPushButton#btnConversations, QPushButton#btnInvites { + border-radius: 0px; + border-top-left-radius: 15px; + border-top-right-radius: 15px; + color: rgb(32, 32, 32); + height: 28px; + padding: 0px; + background-color: rgb(240, 240, 240); + border-top: 2px solid rgb(240, 240, 240); + border-right: 2px solid rgb(240, 240, 240); + border-bottom: 2px solid rgb(240, 240, 240); + border-left: 2px solid rgb(240, 240, 240); +} + +QPushButton#btnConversations:hover, QPushButton#btnInvites:hover { + background-color: rgb(188, 185, 184); + border-top: 2px solid rgb(188, 185, 184); + border-right: 2px solid rgb(188, 185, 184); + border-bottom: 2px solid rgb(188, 185, 184); + border-left: 2px solid rgb(188, 185, 184); +} + +QPushButton#btnConversations:checked, QPushButton#btnInvites:checked { + background-color: rgb(255, 255, 255); + border-bottom: 2px solid rgb(255, 255, 255); +} + +QPushButton#btnConversations:hover:checked, QPushButton#btnInvites:hover:checked { + border-top: 2px solid rgb(240, 240, 240); + border-right: 2px solid rgb(240, 240, 240); + border-bottom: 2px solid rgb(255, 255, 255); + border-left: 2px solid rgb(240, 240, 240); +} + +QPushButton#imBackButton, QPushButton#btnAcceptInvite, QPushButton#btnIgnoreInvite, +QPushButton#btnBlockInvite, QPushButton#btnAudioCall, QPushButton#btnVideoCall, +QPushButton#sendContactRequestButton, QPushButton#sendButton, QPushButton#sendIMButton, +QPushButton#btnExitSettings { + background-color: transparent; + border-style: solid; + border-width: 0px; + border-radius: 15px; + padding: 8px; + color: rgb(32, 32, 32); +} + +QPushButton#btnAcceptInvite:hover, QPushButton#btnIgnoreInvite:hover, QPushButton#btnBlockInvite:hover { + background-color: rgb(212, 212, 212); +} + +QPushButton#btnAcceptInvite:pressed, QPushButton#btnIgnoreInvite:pressed, QPushButton#btnBlockInvite:pressed { + background-color: rgb(187, 187, 187); +} + + QPushButton#imBackButton:hover, QPushButton#btnAudioCall:hover, QPushButton#btnVideoCall:hover, + QPushButton#sendContactRequestButton:hover, QPushButton#sendButton:hover, QPushButton#sendIMButton:hover, + QPushButton#btnExitSettings:hover, QPushButton#btnDeleteAccept:hover, QPushButton#btnDeleteCancel:hover, + QPushButton#changelogButton:hover, QPushButton#creditsButton:hover, QPushButton#changelogButton:hover, QPushButton#updateCancelBtn:hover, + QPushButton#updateAcceptBtn:hover, QPushButton#installBetaButton:hover, QPushButton#closeAboutDialogButton:hover { + background-color: rgb(237, 237, 237); + } + + QPushButton#imBackButton:pressed, QPushButton#btnAudioCall:pressed, QPushButton#btnVideoCall:pressed, + QPushButton#sendContactRequestButton:pressed, QPushButton#sendButton:pressed, QPushButton#sendIMButton:pressed, + QPushButton#btnExitSettings:pressed, QPushButton#btnDeleteAccept:pressed, QPushButton#btnDeleteCancel:pressed, + QPushButton#changelogButton:pressed, QPushButton#creditsButton:pressed, QPushButton#changelogButton:pressed, QPushButton#updateCancelBtn:pressed, + QPushButton#updateAcceptBtn:pressed, QPushButton#installBetaButton:pressed, QPushButton#closeAboutDialogButton:pressed { + background-color: rgb(212, 212, 212); + } + +QWidget#searchBarLayoutWidget, QWidget#smartList, +QWidget#sidePanelLayoutWidget, QWidget#leftSettingsWidget { + border-right: 2px solid rgb(240, 240, 240); +} + +RingContactLineEdit{ + border-radius: 15px; + border: 2px solid rgb(240, 240, 240); + background-color: rgb(240, 240, 240); +} + +RingContactLineEdit:focus{ + border: 2px solid rgb(240, 240, 240); + background-color: rgb(255, 255, 255); +} + +.QLineEdit{ + border-color: rgb(240, 240, 240); + border-radius: 15px; + border-width: 2px; + background-color: rgb(240, 240, 240); + padding-left: 4px; + padding-right: 4px; + height: 30px; +} + +QScrollBar:vertical, QScrollBar:horizontal{ + background:white; width:0px; +} + +QScrollBar::handle:vertical, QScrollBar::handle:horizontal{ + background: rgb(255, 255, 255); +} + +SmartListView { + background-color: white; + border: none; +} + +SmartListView::item:selected, QListView#BannedList::item:selected { + background-color: rgba(220, 220, 220, 255); + border: none; +} + +SmartListView::item:hover, QListView#BannedList::item:hover { + background-color: rgba(242, 242, 242, 255); +} + +QWidget#messagingHeaderWidget { + background-color: rgba(255, 255, 255, 255); + border-bottom: 2px solid rgb(240, 240, 240); +} + +QWidget#messageViewLayoutWidget, QWidget#welcomePage { + background-color: rgba(255, 255, 255, 255); +} + +QPushButton#holdButton, QPushButton#chatButton, QPushButton#noMicButton, QPushButton#noVideoButton, QPushButton#hangupButton, +QPushButton#transferButton, QPushButton#addPersonButton, QPushButton#joinButton, +QPushButton#qualityButton, QPushButton#recButton, QPushButton#transferCallButton, +QPushButton#sipInputPanelButton, QPushButton#addToConferenceButton { + background-color: transparent; + border-radius: 18px; + border: solid 1px; +} + + QPushButton#holdButton:hover, QPushButton#chatButton:hover, QPushButton#noMicButton:hover, QPushButton#hangupButton:hover, + QPushButton#noVideoButton:hover, QPushButton#transferButton:hover, QPushButton#addPersonButton:hover, + QPushButton#joinButton:hover, QPushButton#qualityButton:hover, QPushButton#addToContactButton:hover, + QPushButton#recButton:hover, QPushButton#transferCallButton:hover, + QPushButton#sipInputPanelButton:hover, QPushButton#addToConferenceButton:hover { + background-color: transparent; + border-radius: 18px; + border: solid 1px; + } + + QPushButton#holdButton:pressed, QPushButton#chatButton:pressed, QPushButton#noMicButton:pressed, QPushButton#hangupButton:pressed, + QPushButton#noVideoButton:pressed, QPushButton#transferButton:pressed, QPushButton#addPersonButton:pressed, + QPushButton#joinButton:pressed, QPushButton#qualityButton:pressed, QPushButton#addToContactButton:pressed, + QPushButton#recButton:pressed, QPushButton#addToConferenceButton:pressed { + background-color: transparent; + border-radius: 18px; + border: solid 1px; + } + + QPushButton#holdButton:checked, QPushButton#noMicButton:checked, QPushButton#hangupButton:checked, + QPushButton#noVideoButton:checked, QPushButton#recButton:checked, + QPushButton#chatButton:checked, QPushButton#transferCallButton:checked, + QPushButton#sipInputPanelButton:checked, QPushButton#addToConferenceButton:checked { + background-color: transparent; + border-radius: 18px; + border: solid 1px; + } + +QPushButton#updateCancelButton { + padding: 4px; + background: #369; + color: white; + font-size: 12px; + border: 0; + border-radius: 3px; + outline: 0px; + width: 50px; +} + +QPushButton#updateCancelButton:hover { + background: #47a; +} + +QPushButton#updateCancelButton:pressed { + background: #58b; +} + +QMessageBox QPushButton { + padding: 4px; + background: #369; + color: white; + font-size: 12px; + border: 0; + border-radius: 3px; + outline: 0px; + width: 50px; +} + +QMessageBox QPushButton:hover { + background: #47a; +} + +QMessageBox QPushButton:pressed { + background: #58b; +} + +QToolButton#qrButton, QToolButton#shareButton { + background-color: rgb(242, 242, 242); + border-style: solid; + border-width: 0px; + border-radius: 15px; + padding: 8px; + color: rgb(32, 32, 32); +} + + QToolButton#qrButton:hover, QToolButton#shareButton:hover { + background-color: rgb(237, 237, 237); + } + + QToolButton#qrButton:pressed, QToolButton#shareButton:pressed { + background-color: rgb(212, 212, 212); + } + +QToolButton#qrButton:checked { + background-color: rgb(237, 237, 237); +} + +QPushButton#btnvideo{ + background-color: #109ede; + border-radius: 15px; + border:solid 1px; +} + +QScrollBar:vertical{ + background: rgb(242, 242, 242); + width:10px; +} + +QScrollBar::handle:vertical{ + background: rgb(77, 77, 77); +} + +QWidget#messagingPage, QWidget#contactRequestPage, +QDialog#DeleteAccountDialog, QDialog#UpdateDownloadDialog, +QDialog#UpdateConfirmDialog, QDialog#AccountMigrationDialog { + background: rgb(255, 255, 255); +} + +QWidget#messagingPage { + background: rgb(255, 255, 255); +} + +QDialog#PasswordDialog, +QDialog#LinkDeviceDialog, +QDialog#DeleteAccountDialog { + background: rgb(255, 255, 255); +} + +QPushButton#deleteAccountPushButton { + background-color: red; + border: 0px; + border-radius: 15px; + height: 30px; + color: white; +} + +QPushButton#deleteAccountPushButton:hover { + background-color: rgb(230, 0, 0); +} + +QPushButton#deleteAccountPushButton:disabled { + background-color: rgba(255, 0, 0, 0.8); +} + +QPushButton#nextButton, QPushButton#playButton, QPushButton#clearHistoryButton, QPushButton#doTransferButton, +QPushButton#photoButton, QPushButton#migrationPushButton, +QPushButton#fromDeviceButton, QPushButton#newAccountButton, QPushButton#previousButton, QPushButton#exportButton, QPushButton#newSIPAccountButton, QPushButton#fromBackupButton, QPushButton#connectAccountManagerButton, +QPushButton#cancelAddButton, QPushButton#exportOnRingButton, QPushButton#addDeviceButton, QPushButton#exportEndedOkButton, +QPushButton#errorPushButton, QPushButton#registerButton, QPushButton#acceptCRButton, QPushButton#discardCRButton, QPushButton#deleteCancelBtn, +QPushButton#skipBtn, QPushButton#exportBtn, +QPushButton#dhtImportBtn, QPushButton#fileImportBtn, QPushButton#changePassBtn, QPushButton#confirmChangeBtn, QPushButton#backButton { + background: qlineargradient(x1: 0, y1: 0, x2: 1, y2: 0, stop: 0 #109ede, stop: 1.0 #2b5084); + border: 0px; + border-radius: 15px; + height: 30px; + color: white; +} + +QPushButton#nextButton:disabled, QPushButton#playButton:disabled, QPushButton#clearHistoryButton:disabled, +QPushButton#doTransferButton:disabled, QPushButton#photoButton:disabled, QPushButton#fromBackupButton:disabled +QPushButton#existingPushButton:disabled, QPushButton#newAccountButton:disabled, QPushButton#previousButton:disabled, QPushButton#newSIPAccountButton:disabled, +QPushButton#exportButton:disabled, QPushButton#cancelAddButton:disabled, QPushButton#exportOnRingButton:disabled, +QPushButton#addDeviceButton:disabled, QPushButton#exportEndedOkButton:disabled, QPushButton#errorPushButton:disabled, +QPushButton#registerButton:disabled, QPushButton#acceptCRButton:disabled, QPushButton#discardCRButton:disabled, +QPushButton#deleteCancelBtn:disabled, QPushButton#dhtImportBtn:disabled, QPushButton#fileImportBtn:disabled, +QPushButton#changePassBtn:disabled, QPushButton#confirmChangeBtn:disabled, QPushButton#backButton:disabled, +QPushButton#fromDeviceButton:disabled, QPushButton#connectAccountManagerButton:disabled, QPushButton#exportBtn:disabled, +QPushButton#skipBtn:disabled, QPushButton#migrationPushButton:disabled { + background: rgba(242, 242, 242, 0.8); + color: grey; +} + +QPushButton#blockCRButton, QPushButton#debanButton, QPushButton#deleteBanBtn, +QPushButton#cancelChangeBtn { + background-color: rgb(251, 72, 71); + border: 0px; + color: white; +} + +QPushButton#nextButton:hover, QPushButton#playButton:hover, QPushButton#clearHistoryButton:hover, +QPushButton#doTransferButton:hover, QPushButton#photoButton:hover, QPushButton#fromBackupButton:hover, +QPushButton#existingPushButton:hover, QPushButton#newAccountButton:hover, QPushButton#previousButton:hover, QPushButton#newSIPAccountButton:hover, +QPushButton#exportButton:hover, QPushButton#cancelAddButton:hover, QPushButton#exportOnRingButton:hover, +QPushButton#addDeviceButton:hover, QPushButton#exportEndedOkButton:hover, QPushButton#errorPushButton:hover, +QPushButton#registerButton:hover, QPushButton#acceptCRButton:hover, QPushButton#discardCRButton:hover, +QPushButton#deleteCancelBtn:hover, QPushButton#dhtImportBtn:hover, QPushButton#fileImportBtn:hover, QPushButton#migrationPushButton:hover, +QPushButton#changePassBtn:hover, QPushButton#confirmChangeBtn:hover, QPushButton#backButton:hover, QPushButton#skipBtn:hover, +QPushButton#fromDeviceButton:hover, QPushButton#connectAccountManagerButton:hover, QPushButton#exportBtn:hover { + background: qlineargradient(x1: 0, y1: 0, x2: 1, y2: 0, stop: 0 #2b4b7e, stop: 1.0 #001d4d); + color: white; +} + +QPushButton#blockCRButton:hover, QPushButton#deleteAcceptBtn:hover, QPushButton#debanButton:hover, +QPushButton#deleteButton:hover, QPushButton#deleteBanBtn:hover, QPushButton#cancelChangeBtn:hover { + background-color: rgb(252, 91, 90); +} + +QPushButton#nextButton:pressed, QPushButton#playButton:pressed, QPushButton#clearHistoryButton:pressed, +QPushButton#doTransferButton:pressed, QPushButton#photoButton:pressed, QPushButton#skipBtn:pressed, QPushButton#migrationPushButton:pressed, +QPushButton#existingPushButton:pressed, QPushButton#newAccountButton:pressed, QPushButton#previousButton:pressed, QPushButton#newSIPAccountButton:pressed, +QPushButton#exportButton:pressed, QPushButton#cancelAddButton:pressed, QPushButton#exportOnRingButton:pressed, +QPushButton#addDeviceButton:pressed, QPushButton#exportEndedOkButton:pressed, QPushButton#errorPushButton:pressed, +QPushButton#registerButton:pressed, QPushButton#acceptCRButton:pressed, QPushButton#discardCRButton:pressed, +QPushButton#deleteCancelBtn:pressed, QPushButton#dhtImportBtn:pressed, QPushButton#fileImportBtn:pressed, +QPushButton#changePassBtn:pressed, QPushButton#confirmChangeBtn:pressed, QPushButton#backButton:pressed, QPushButton#exportBtn:pressed { + background: qlineargradient(x1: 0, y1: 0, x2: 1, y2: 0, stop: 0 #043161, stop: 1.0 #00113f); + color: white; +} + +QPushButton#blockCRButton:pressed, QPushButton#deleteAcceptBtn:pressed, QPushButton#debanButton:pressed, +QPushButton#deleteBanBtn:pressed, QPushButton#cancelChangeBtn:pressed{ + background-color: rgb(219, 55, 54); +} + +QPushButton#btnChangePasswordCancel { + background-color: rgb(252, 91, 90); + color: white; +} + +QPushButton#btnChangePasswordCancel:hover { + background-color: red; + color: white; +} + +QPushButton#btnChangePasswordCancel:pressed { + background-color: darkred; + color: white; +} + +QComboBox{ + background: transparent; + border-radius: 0px; + border-style: solid; + border-width: 2px; + border-color: #414141; + border-bottom: transparent; + border-top: transparent; + border-left: transparent; + border-right: transparent; + font-family: "Sans Serif"; + padding: 2px; +} + +QComboBox::down-arrow{ + border-radius: 0px; + border-style: solid; + border-width: 2px; + height: 36; + width : 36; + image: url(":/images/icons/ic_arrow_drop_down_black_18dp_2x.png"); +} + +QComboBox::drop-down{ + border: 0; + width: 36px; +} + +QRadioButton::indicator{ + width: 1 ; + height: 12px; + border-radius: 8px; + border-width: 2px; + border-style: solid; +} + +QRadioButton::indicator:unchecked{ + border-color: rgb(77, 77, 77); + background: transparent; +} + +QRadioButton::indicator:checked{ + background: #109ede; + border-color: #109ede; + image: url(":/images/icons/ic_check_white_18dp_2x.png"); +} + +QWidget#horizontalWidget{ + background: transparent; +} + +QCheckBox::indicator{ + height : 12 px; + width : 12 px; + border: 2px solid rgb(77, 77, 77); + border-radius: 4px; + background: none; +} + +QCheckBox::indicator:checked{ + border-color: #2b4b7e; + background: #2b4b7e; + image: url(":/images/icons/ic_check_white_18dp_2x.png"); +} + +QSpinBox::down-button{ + height: 9; + width : 9; + image: url(":/images/icons/ic_arrow_drop_down_black_9dp_2x.png"); +} + +QSpinBox::up-button{ + height: 9; + width : 9; + image: url(":/images/icons/ic_arrow_drop_up_black_9dp_2x.png"); +} + +QLineEdit#lrcfg_alias:focus, QLineEdit#lrcfg_hostname:focus, QLineEdit#lrcfg_password:focus, +QLineEdit#lrcfg_proxy:focus, QLineEdit#lrcfg_mailbox:focus, QLineEdit#lrcfg_tlsPassword:focus, +QLineEdit#lrcfg_tlsServerName:focus, QLineEdit#lrcfg_turnServerRealm:focus, QLineEdit#lrcfg_turnServerUsername:focus, +QLineEdit#lrcfg_turnServerPassword:focus, QLineEdit#lrcfg_turnServer:focus, QLineEdit#lrcfg_publishedAddress:focus, +QLineEdit#lrcfg_registeredName:focus, QLineEdit#lrcfg_nameServiceURL:focus, QLineEdit#lrcfg_username:focus, +QLineEdit#profileNameEdit:focus{ + border-color: #109ede; +} + +QTabWidget#tabWidget{ + border-color: transparent; +} + +QPushButton#upAudioButton, QPushButton#downAudioButton, QPushButton#upVideoButton, QPushButton#downVideoButton{ + background: transparent; +} + +QPushButton#avatarButton:hover { + border: 2px solid rgb(77, 77, 77); + border-radius: 50px; +} + +QWidget#leftPannel{ + background: white; +} + +QSlider::groove:vertical{ + background: red; + position: absolute; /* absolutely position 4px from the left and right of the widget. setting margins on the widget should work too... */ + width:2px; +} + +QSlider::handle:vertical{ + height: 10px; + background: #109ede; + border-radius: 5px; + margin: 0 -4px; +} + +QSlider::sub-page:vertical{ + background: #777777; +} + +QSlider::add-page:vertical{ + background: #109ede; +} + +QToolButton::menu-button {image:none;} + +QToolButton::menu-arrow {image:none;} + +QLabel#accountIdLabel, QLabel#accountAliasLabel, QLabel#deletionLabel1, QLabel#deletionLabel2, +QLabel#warningLabel{ + background: transparent; +} + +QLabel#accountAliasLabel, QLabel#deletionLabel1, QLabel#deletionLabel2{ + color: black; +} + +QLabel#warningLabel{ + color: red; +} + +QLabel#labelWarning { + color: darkorange; +} + +QLabel#accountIdLabel{ + color: LightSlateGrey; + font-style: italic; +} + +QLabel#accountAliasLabel{ + font-weight: bold; +} + +QLabel#dragDropLabel { + /*rgba 0.95 opacity (transparency)*/ + font-size: 20px; + border: 2px dashed black; + border-radius: 10px; + background: rgba(216, 234, 252, 0.95); +} + +/* setAvatarDialog { */ +QPushButton#pictureButton:default, QPushButton#fileButton:default { + background-color: rgb(0, 192, 213,); +} + +QPushButton#pictureButton:checked, QPushButton#fileButton:checked { + background-color: rgb(0, 0, 213); +} +/* } setAvatarDialog */ + +QSpinBox { + background-color: rgb(240, 240, 240); + border-radius: 14px; + height: 28px; + padding: 2px; + margin-bottom: 4px; +} + +QSpinBox::up-button { + subcontrol-origin: border; + subcontrol-position: top right; + width: 16px; + height: 18px; + padding-right: 4px; + margin-top: 3px; +} + +QSpinBox::down-button { + subcontrol-origin: border; + subcontrol-position: bottom right; + width: 16px; + height: 18px; + padding-right: 4px; + margin-bottom: 3px; +} + +/* SettingsWidget { */ +SettingsWidget QLabel#wrongPasswordLabel { + color: red; + margin-left: 8px; +} +SettingsWidget QLabel#exportedPIN { + color: darkblue; + margin-bottom: 4px; +} + +SettingsWidget QPushButton { + padding-right: 16px; + padding-left: 16px; + border-style: solid; + border-width: 0px; + border-radius: 15px; + color: rgb(32, 32, 32); + background-color: rgb(242, 242, 242); +} + +SettingsWidget QPushButton:hover { + background-color: rgb(237, 237, 237); +} + +SettingsWidget QPushButton:pressed { + background-color: rgb(212, 212, 212); +} + +SettingsWidget QPushButton:disabled { + color: gray; +} + +SettingsWidget QLabel:disabled { + color: rgb(160, 160, 160); +} + +SettingsWidget QWidget#leftSettingsWidget, +SettingsWidget QWidget#rightSettingsWidget, +SettingsWidget QWidget#DeleteAccountDialog, +SettingsWidget QWidget#advancedSettingsWidget, +SettingsWidget QWidget#advancedSIPSettingsWidget, +SettingsWidget QWidget#NameRegistrationDialog, +SettingsWidget QWidget#centralWidget, +SettingsWidget QWidget#centralSIPWidget, +SettingsWidget QWidget#scrollAreaWidgetContents, +SettingsWidget QWidget#scrollAreaSIPWidgetContents { + background-color: rgba(255, 255, 255, 255); +} + +SettingsWidget .QLineEdit { + border-radius: 15px; + background-color: rgb(240, 240, 240); + padding-left: 8px; + padding-right: 8px; + height: 30px; +} + +SettingsWidget QLineEdit#currentRingID { + border: 0px; + border-radius: 0px; + padding: 0px; + background-color: transparent; + font-weight: bold; +} + +SettingsWidget QLineEdit#currentRegisteredID { + border: 2px; + border-radius: 15px; + padding: 1px; + padding-left: 8px; + margin-right: 4px; + border-style: solid; + background-color: rgb(240, 240, 240); +} + +SettingsWidget QPushButton#regNameButton { + background-color: transparent; +} + +SettingsWidget QWidget#videoLayoutWidget { + background-color: black; +} + +SettingsWidget QPushButton#btnDeletAccount, +SettingsWidget QPushButton#btnSIPDeletAccount { + background-color: rgb(252, 91, 90); + color: white; +} + +SettingsWidget QPushButton#btnDeletAccount:hover, +SettingsWidget QPushButton#btnSIPDeletAccount:hover { + background-color: red; + color: white; +} + +SettingsWidget QPushButton#btnDeletAccount:pressed, +SettingsWidget QPushButton#btnSIPDeletAccount:pressed { + background-color: darkred; + color: white; +} + +QListView .QLabel#labelDeviceId { + padding-left: 4px; + font-weight: 300; +} + +QListView .QLabel#labelThisDevice { + margin-right: 16px; + font-style: italic; + color: green; +} + +QListWidget .QLabel { + background-color: transparent; +} + +QListWidget .QLineEdit { + background-color: transparent; +} + +QListWidget .QPushButton { + background-color: transparent; +} + QListWidget .QPushButton:hover { + background-color: transparent; + } + QListWidget .QPushButton:pressed { + background-color: transparent; + } + +QListView::item:selected { + background-color: rgb(220, 220, 220); +} + +SettingsWidget QListView { + background-color: whitesmoke; + border: 1px solid rgb(212, 212, 212); + font-size: 16px; +} + +SettingsWidget QListView::item { + height: 30px; + font: 30px; + padding: 8px; +} + +SettingsWidget QListView::indicator { + height: 12 px; + width: 12 px; + border: 2px solid rgb(77, 77, 77); + border-radius: 4px; + background: none; +} + +SettingsWidget QListView::indicator:checked { + border-color: #2b4b7e; + background: #2b4b7e; + image: url(":/images/icons/ic_check_white_18dp_2x.png"); +} + +SettingsWidget QListView::item:selected { + background-color: rgba(220, 220, 220, 255); + border: none; + color: black; +} + +SettingsWidget QListView::item:hover { + background-color: rgba(229, 229, 229, 255); +} + +SettingsWidget QListView::item:disabled { + background-color: transparent; +} + +/* } SettingsWidget */ + +QPushButton#panelButton_0, QPushButton#panelButton_1, QPushButton#panelButton_2, +QPushButton#panelButton_3, QPushButton#panelButton_4, QPushButton#panelButton_5, +QPushButton#panelButton_6, QPushButton#panelButton_7, QPushButton#panelButton_8, +QPushButton#panelButton_9, QPushButton#panelButton_hash, QPushButton#panelButton_A, +QPushButton#panelButton_B, QPushButton#panelButton_C, QPushButton#panelButton_D { + text-align: center; + text-decoration: none; + background: #369; + color: white; + border: 0; + border-radius: 19px; + padding-bottom: 4px; +} + +QPushButton#panelButton_star { + text-align: center; + text-decoration: none; + background: #369; + color: white; + border: 0; + border-radius: 19px; + padding-top: 4px; +} + +QPushButton#panelButton_0:hover, QPushButton#panelButton_1:hover, QPushButton#panelButton_2:hover, +QPushButton#panelButton_3:hover, QPushButton#panelButton_4:hover, QPushButton#panelButton_5:hover, +QPushButton#panelButton_6:hover, QPushButton#panelButton_7:hover, QPushButton#panelButton_8:hover, +QPushButton#panelButton_9:hover, QPushButton#panelButton_hash:hover, QPushButton#panelButton_star:hover, +QPushButton#panelButton_A:hover, QPushButton#panelButton_B:hover, QPushButton#panelButton_C:hover, +QPushButton#panelButton_D:hover { + background: #47a; +} + +QPushButton#panelButton_0:pressed, QPushButton#panelButton_1:pressed, QPushButton#panelButton_2:pressed, +QPushButton#panelButton_3:pressed, QPushButton#panelButton_4:pressed, QPushButton#panelButton_5:pressed, +QPushButton#panelButton_6:pressed, QPushButton#panelButton_7:pressed, QPushButton#panelButton_8:pressed, +QPushButton#panelButton_9:pressed, QPushButton#panelButton_hash:pressed, QPushButton#panelButton_star:pressed, +QPushButton#panelButton_A:pressed, QPushButton#panelButton_B:pressed, QPushButton#panelButton_C:pressed, +QPushButton#panelButton_D:pressed { + background: #58b; +} + +QProgressBar#audioInputMeter { + border: 0px solid #606060; + background: lightgrey; +} + + QProgressBar#audioInputMeter::chunk { + background-color: #0c79aa; + margin: 2px; + } + +QLabel#nameLabel { + font-size: 20px; + font-style: initial; + qproperty-alignment: AlignCenter; + color: white; +} + +QWidget#videoPage { + background: black; +} + +QPushButton#recordOverlayStartOrFinishRecordingBtn, QPushButton#recordOverlayDeleteBtn, QPushButton#recordOverlayPlayBtn, QPushButton#recordOverlayRerecordBtn, QPushButton#recordOverlaySendBtn, +QPushButton#recordOverlayStopPlayingBtn { + background-color: transparent; + border-radius: 18px; + border: solid 1px; +} + +QPushButton#recordOverlayStartOrFinishRecordingBtn:hover, QPushButton#recordOverlayDeleteBtn:hover, QPushButton#recordOverlayPlayBtn:hover, QPushButton#recordOverlayRerecordBtn:hover, QPushButton#recordOverlaySendBtn:hover, +QPushButton#recordOverlayStopPlayingBtn:hover { + background-color: transparent; + border-radius: 18px; + border: solid 1px; +} + +QPushButton#recordOverlayStartOrFinishRecordingBtn:pressed, QPushButton#recordOverlayDeleteBtn:pressed, QPushButton#recordOverlayPlayBtn:pressed, QPushButton#recordOverlayRerecordBtn:pressed, QPushButton#recordOverlaySendBtn:pressed, +QPushButton#recordOverlayStopPlayingBtn:pressed { + background-color: transparent; + border-radius: 18px; + border: solid 1px; +} + +QPushButton#recordOverlayStartOrFinishRecordingBtn:checked, QPushButton#recordOverlayDeleteBtn:checked, QPushButton#recordOverlayPlayBtn:checked, QPushButton#recordOverlayRerecordBtn:checked, QPushButton#recordOverlaySendBtn:checked, +QPushButton#recordOverlayStopPlayingBtn:checked { + background-color: transparent; + border-radius: 18px; + border: solid 1px; +} + +QWidget#RecordWidget { + background-color: transparent; +} + +QLabel#timerLabel { + background-color: transparent; + color: white; +} + +QProgressBar#levelMeter { + border: 2px solid white; + text-align: center; + background: transparent; +} + + QProgressBar#levelMeter::chunk { + background-color: white; + margin: 2px; + } + +QScrollArea#changeLogScrollArea { + background-color: transparent; + color: white; + border: none; +} + +QWidget#changeLogContents { + background-color: transparent; + color: white; + border: none; +} + +QTextEdit#logTextEdit { + background-color: white; + color: black; +} + +QPushButton#logCloseButton { + background-color: rgb(189, 189, 189); +} + + QPushButton#logCloseButton:hover { + background-color: rgb(170, 170, 170); + } + QPushButton#logCloseButton:pressed { + background-color: rgb(180, 180, 180); + } + +FullScreenNotification { + font-size: 24px; + color: white; + background-color: black; + border: 2px solid white; + padding: 100px; +} \ No newline at end of file diff --git a/translations/ring_client_windows.ts b/translations/ring_client_windows.ts new file mode 100644 index 00000000..d6ca7236 --- /dev/null +++ b/translations/ring_client_windows.ts @@ -0,0 +1,1591 @@ + + + + + AboutDialog + + + + About + + + + + about button + + + + + credits button + + + + + Credits + + + + + Free as in Freedom + + + + + The Microsoft Windows client for Jami. +Jami is a secured and distributed communication software. + + + + + version + + + + + Created by: + + + + + Artwork by: + + + + + Based on the SFLPhone project + + + + + AccountItemDelegate + + + Add Account + + + + + AdvancedSIPSettingsWidget + + + Form + + + + + Call Settings + + + + + Auto Answer Calls + + + + + Enable Custom Ringtone + + + + + Connectivity + + + + + STUN Address + + + + + Use STUN + + + + + Use UPnP + + + + + Use TURN + + + + + TURN Password + + + + + TURN Username + + + + + TURN Address + + + + + Media + + + + + Enable Video + + + + + Video Codecs + + + + + Audio Codecs + + + + + Audio Files (*.wav *.ogg *.opus *.mp3 *aiff *wma) + + + + + Add a custom ringtone + + + + + AdvancedSettingsWidget + + + Form + + + + + Call Settings + + + + + Allow Calls From Untrusted Peers + + + + + Auto Answer Calls + + + + + Enable Custom Ringtone + + + + + Add a custom ringtone + + + + + Name Server + + + + + Address + + + + + OpenDHT Configuration + + + + + Enable Proxy + + + + + Bootstrap + + + + + Security + + + + + Private Key Password + + + + + User Certificate + + + + + Private Key + + + + + CA Certificate + + + + + Connectivity + + + + + Use STUN + + + + + STUN Address + + + + + Use UPnP + + + + + Use TURN + + + + + TURN Password + + + + + TURN Username + + + + + TURN Address + + + + + Media + + + + + Enable Video + + + + + Audio Codecs + + + + + Video Codecs + + + + + Audio Files (*.wav *.ogg *.opus *.mp3 *aiff *wma) + + + + + AnimatedOverlay + + + Form + + + + + BannedItemWidget + + + Form + + + + + name + + + + + id + + + + + CallWidget + + + Show conversations + + + + + Conversations + + + + + Search contact text input + + + + + Jami is free software for universal communication which respects the freedoms and privacy of its users. + + + + + + This is your ID. +Copy and share it with your friends! + + + + + + Show ring ID QR code + + + + + Share ring ID button + + + + + Double-click to copy + + + + + Error while generating QR Code + + + + + + best name + + + + + best Id + + + + + Back to homepage button + + + + + Add to contacts + + + + + Show invites + + + + + Invites + + + + + + Find a new or existing contact + + + + + Wants to talk to you! + + + + + Answer incoming call button + + + + + Ignore incoming call button + + + + + Answer + + + + + Ignore + + + + + Cancel outgoing call + + + + + Cancel + + + + + Start video call + + + + + Start audio call + + + + + Clear conversation + + + + + Remove contact + + + + + Block contact + + + + + Copy number + + + + + Search your received invitations + + + + + Contact me on Jami + + + + + My Id is : + + + + + %1 + %1 is the contact username + + + + + %1 + %1 is the contact unique identifier + + + + + Call incoming from %1 + + + + + DeleteAccountDialog + + + Account deletion + + + + + Do you really want to delete the following account? + + + + + If this account hasn't been exported, or added to another device, it will be irrevocably lost. + + + + + Permanently delete account + + + + + Delete + + + + + Cancel account deletion + + + + + Cancel + + + + + DeviceItemWidget + + + Form + + + + + Device Id + + + + + this device + + + + + InviteButtonsWidget + + + Accept + + + + + Refuse + + + + + Block + + + + + LinkDeviceDialog + + + Dialog + + + + + Enter your account password + + + + + Password + + + + + Ok + + + + + Cancel + + + + + Exporting account + + + + + Your PIN is + + + + + PIN + + + + + This pin and the account password should be entered in your device within 10 minutes. + + + + + Close + + + + + Link Another Device + + + + + Incorrect password + + + + + Something went wrong. +Please try again later. + + + + + MainWindow + + + Settings + + + + + Exit + + + + + About + + + + + Jami + + + + + NameRegistrationDialog + + + Set Registered Name + + + + + Enter your account password + + + + + Password text input + + + + + Password text entry + + + + + Password + + + + + Register + + + + + Cancel + + + + + Registering Name + + + + + Something went wrong + + + + + Close + + + + + Incorrect password + + + + + Network error + + + + + NewWizardWidget + + + Form + + + + + Welcome Label + + + + + Welcome to + + + + + Welcome Logo + + + + + Create Jami account button + + + + + Push button for Jami account creation start trigger + + + + + Create a Jami account + + + + + Link device button + + + + + Push button for device linkage start trigger + + + + + Link this device to an account + + + + + Create Jami SIP account button + + + + + Push button for Jami SIP account creation start trigger + + + + + Create a SIP account + + + + + Link this device to an existing account + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Ubuntu'; font-size:14px; color:#555555;">To link this device to another account, you first </span><span style=" font-family:'Ubuntu'; font-size:14px; font-weight:600; color:#555555;">need to obtain a PIN</span><span style=" font-family:'Ubuntu'; font-size:14px; color:#555555;"> code. To generate the PIN code:</span></p> +<ol style="margin-top: 0px; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; -qt-list-indent: 1;"><li style=" font-family:'Ubuntu'; font-size:14px; color:#555555;" style=" margin-top:12px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:14px;">Go to the </span><span style=" font-size:14px; font-weight:600;">Account management setting</span><span style=" font-size:14px;"> of a previous device</span></li> +<li style=" font-family:'Ubuntu'; font-size:14px; color:#555555;" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:14px;">Choose the </span><span style=" font-size:14px; font-weight:600;">Jami account</span><span style=" font-size:14px;"> you want to use</span></li> +<li style=" font-family:'Ubuntu'; font-size:14px; color:#555555;" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:14px;">Go to the </span><span style=" font-size:14px; font-weight:600;">Devices</span><span style=" font-size:14px;"> tab</span></li> +<li style=" font-family:'Ubuntu'; font-size:14px; color:#555555;" style=" margin-top:0px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:14px;">Select </span><span style=" font-size:14px; font-weight:600;">Add a device</span></li></ol> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Ubuntu'; font-size:14px; color:#555555;">You will get the necessary PIN to complete this form. The PIN is only valid for </span><span style=" font-family:'Ubuntu'; font-size:14px; font-weight:600; color:#555555;">10 minutes</span><span style=" font-family:'Ubuntu'; font-size:10px; color:#555555;">.</span></p></body></html> + + + + + Enter your pin: + + + + + Or import a file: + + + + + Link from exported account archive file + + + + + + + (None) + + + + + Password: + + + + + + Profile + + + + + + Profile name + + + + + Account + + + + + Register your username. +This will reserve the username so that only you can use it. +Your friends will be able to call you with your usename +instead of using your ID. + + + + + Public username checkbox + + + + + Checkbox selecting if the user wants a public username + + + + + Register public username + + + + + Public username edit + + + + + Choose your username + + + + + Password text input + + + + + Password text entry + + + + + + Password + + + + + + Password confirmation text input + + + + + Confirm password + + + + + SIP Account + + + + + SIP Server edit + + + + + Server + + + + + SIP proxy input + + + + + SIP proxy text entry + + + + + Proxy + + + + + SIP username input + + + + + SIP Password text entry + + + + + Username + + + + + + SIP Password text input + + + + + Generating your Jami account… + + + + + Previous page button + + + + + push button to access previous page of wizard + + + + + Previous + + + + + Cancel account create/link + + + + + push button to cancel account creation or linking + + + + + Back + + + + + Next page Button + + + + + Push button to access next page of wizard + + + + + Next + + + + + Open File + + + + + Jami archive files (*.gz); All files (*) + + + + + Your account needs to be migrated. Enter your password. + + + + + Migrating your Jami account... + + + + + Importing account archive... + + + + + Generating your Jami account... + + + + + Generating your SIP account... + + + + + Error creating account + + + + + PasswordDialog + + + Change Account Password + + + + + Enter Current Password + + + + + Enter New Password + + + + + Confirm New Password + + + + + Confirm + + + + + Cancel + + + + + Current Password Incorrect + + + + + PhotoBoothDialog + + + Photobooth + + + + + PhotoboothWidget + + + Form + + + + + Photobooth display + + + + + Choose File + + + + + Image Files (*.jpg *.jpeg *.png) + + + + + PrivateBridging + + + Choose File + + + + + Files (*) + + + + + QObject + + + No default mail client found + + + + + + Edit Device Name + + + + + Unlink Device From Account + + + + + Save new device name + + + + + Add as contact + + + + + RingButton + + + Select folder + + + + + SettingsWidget + + + Form + + + + + Settings + + + + + Account + + + + + + General + + + + + + Audio / Video + + + + + System + + + + + Enable desktop notifications + + + + + Keep minimized on close + + + + + Download folder + + + + + Save in + + + + + Always Recording + + + + + Updates + + + + + Check for updates automatically every + + + + + Interval between update checks in days selector + + + + + days + + + + + Check for updates now button + + + + + Check for updates now + + + + + Password + + + + + + Enable + + + + + toggle enable notifications + + + + + Toggle keep minimized on close + + + + + Call Recordings + + + + + Toggle automatic updates + + + + + Jami Account + + + + + + Profile + + + + + + Identity + + + + + Id + + + + + Registered name + + + + + Type here to register a username + + + + + Register + + + + + Change Password + + + + + Export Account + + + + + + Delete Account + + + + + Linked Devices + + + + + Link Another Device + + + + + Banned Contacts + + + + + Format + + + + + Video device framerate selector + + + + + Preview unavailable + + + + + + Advanced Account Settings + + + + + SIP Account + + + + + Username + + + + + Hostname + + + + + Proxy + + + + + Audio + + + + + Microphone + + + + + Audio input device selector + + + + + Output Device + + + + + Choose the output device + + + + + Video + + + + + Device + + + + + Video device selector + + + + + A registered name should not have any spaces and must be at least three letters long + + + + + This name is already taken + + + + + + Enter an alias + + + + + Register this name + + + + + Remove Device + + + + + Enter this account's password to confirm the removal of this device + + + + + Are you sure you wish to remove this device? + + + + + Export Account Here + + + + + Select A Folder For Your Downloads + + + + + Select A Folder For Your Recordings + + + + + VideoOverlay + + + Call on Hold + + + + + Hold / Unhold + + + + + Chat + + + + + Mute Mic + + + + + Record call + + + + + Name label + + + + + Time elapsed + + + + + 00:00 + + + + + Hangup + + + + + Mute Video + + + + + VideoView + + + Share entire screen + + + + + Share screen area + + + + + Share file + + + + diff --git a/translations/ring_client_windows_ar.ts b/translations/ring_client_windows_ar.ts new file mode 100644 index 00000000..c30e9633 --- /dev/null +++ b/translations/ring_client_windows_ar.ts @@ -0,0 +1,1589 @@ + + + AboutDialog + + + + About + عن RING + + + + about button + + + + + credits button + + + + + Credits + الأطراف المصممة + + + + Free as in Freedom + + + + + The Microsoft Windows client for Jami. +Jami is a secured and distributed communication software. + + + + + version + الإصدار + + + + Created by: + أحدثه: + + + + Artwork by: + مصمم العمل الفني: + + + + Based on the SFLPhone project + يستند على مشروع SFLPhone + + + + AccountItemDelegate + + + Add Account + + + + + AdvancedSIPSettingsWidget + + + Form + استمارة + + + + Call Settings + + + + + Auto Answer Calls + + + + + Enable Custom Ringtone + + + + + Connectivity + الاتصال + + + + STUN Address + + + + + Use STUN + إستعمل STUN + + + + Use UPnP + + + + + Use TURN + إستعمل TURN + + + + TURN Password + + + + + TURN Username + + + + + TURN Address + + + + + Media + ميديا + + + + Enable Video + فعل الفيديو + + + + Video Codecs + + + + + Audio Codecs + + + + + Audio Files (*.wav *.ogg *.opus *.mp3 *aiff *wma) + + + + + Add a custom ringtone + + + + + AdvancedSettingsWidget + + + Form + استمارة + + + + Call Settings + + + + + Allow Calls From Untrusted Peers + + + + + Auto Answer Calls + + + + + Enable Custom Ringtone + + + + + Add a custom ringtone + + + + + Name Server + + + + + Address + العنوان + + + + OpenDHT Configuration + + + + + Enable Proxy + + + + + Bootstrap + تشغيل ذاتي + + + + Security + تأمين + + + + Private Key Password + كلمة سر المفتاح الخاص + + + + User Certificate + شهادة المستخدم + + + + Private Key + + + + + CA Certificate + + + + + Connectivity + الاتصال + + + + Use STUN + إستعمل STUN + + + + STUN Address + + + + + Use UPnP + + + + + Use TURN + إستعمل TURN + + + + TURN Password + + + + + TURN Username + + + + + TURN Address + + + + + Media + ميديا + + + + Enable Video + فعل الفيديو + + + + Audio Codecs + + + + + Video Codecs + + + + + Audio Files (*.wav *.ogg *.opus *.mp3 *aiff *wma) + + + + + AnimatedOverlay + + + Form + استمارة + + + + BannedItemWidget + + + Form + استمارة + + + + name + + + + + id + + + + + CallWidget + + + Show conversations + + + + + Conversations + محادثات + + + + Search contact text input + + + + + Jami is free software for universal communication which respects the freedoms and privacy of its users. + جامي هو برنامج حر للتواصل العالمي الذي يحترم حريات و خصوصيات مستخدميه. + + + + + This is your ID. +Copy and share it with your friends! + + + + + + Show ring ID QR code + + + + + Share ring ID button + + + + + Double-click to copy + + + + + Error while generating QR Code + خطأ عند محاولة تولد الرمز الشريطي + + + + + best name + + + + + best Id + + + + + Back to homepage button + + + + + Add to contacts + أضف إلى الاتصالات المعروفة + + + + Show invites + + + + + Invites + + + + + + Find a new or existing contact + + + + + Wants to talk to you! + يريد التحدث إليك! + + + + Answer incoming call button + + + + + Ignore incoming call button + + + + + Answer + أجب + + + + Ignore + تجاهل + + + + Cancel outgoing call + + + + + Cancel + ألغِ + + + + Start video call + + + + + Start audio call + + + + + Clear conversation + + + + + Remove contact + + + + + Block contact + حظر جهة إتصال + + + + Copy number + نسخ الرقم + + + + Search your received invitations + + + + + Contact me on Jami + + + + + My Id is : + + + + + %1 + %1 is the contact username + + + + + %1 + %1 is the contact unique identifier + + + + + Call incoming from %1 + مكالمة قادمة من %1 + + + + DeleteAccountDialog + + + Account deletion + + + + + Do you really want to delete the following account? + + + + + If this account hasn't been exported, or added to another device, it will be irrevocably lost. + + + + + Permanently delete account + + + + + Delete + إحذف + + + + Cancel account deletion + + + + + Cancel + ألغِ + + + + DeviceItemWidget + + + Form + استمارة + + + + Device Id + + + + + this device + + + + + InviteButtonsWidget + + + Accept + اقبل + + + + Refuse + أرفض + + + + Block + حظر + + + + LinkDeviceDialog + + + Dialog + الحوار + + + + Enter your account password + + + + + Password + كلمة السر + + + + Ok + موافق + + + + Cancel + ألغِ + + + + Exporting account + + + + + Your PIN is + + + + + PIN + رمز الأمان + + + + This pin and the account password should be entered in your device within 10 minutes. + + + + + Close + + + + + Link Another Device + + + + + Incorrect password + + + + + Something went wrong. +Please try again later. + + + + + MainWindow + + + Settings + إعدادات + + + + Exit + غادر + + + + About + عن RING + + + + Jami + جامي + + + + NameRegistrationDialog + + + Set Registered Name + + + + + Enter your account password + + + + + Password text input + + + + + Password text entry + + + + + Password + كلمة السر + + + + Register + سجل + + + + Cancel + ألغِ + + + + Registering Name + + + + + Something went wrong + + + + + Close + + + + + Incorrect password + + + + + Network error + + + + + NewWizardWidget + + + Form + استمارة + + + + Welcome Label + + + + + Welcome to + + + + + Welcome Logo + + + + + Create Jami account button + + + + + Push button for Jami account creation start trigger + + + + + Create a Jami account + كوّن حساب جامي + + + + Link device button + + + + + Push button for device linkage start trigger + + + + + Link this device to an account + اربط هذا الجهاز مع حساب + + + + Create Jami SIP account button + + + + + Push button for Jami SIP account creation start trigger + + + + + Create a SIP account + + + + + Link this device to an existing account + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Ubuntu'; font-size:14px; color:#555555;">To link this device to another account, you first </span><span style=" font-family:'Ubuntu'; font-size:14px; font-weight:600; color:#555555;">need to obtain a PIN</span><span style=" font-family:'Ubuntu'; font-size:14px; color:#555555;"> code. To generate the PIN code:</span></p> +<ol style="margin-top: 0px; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; -qt-list-indent: 1;"><li style=" font-family:'Ubuntu'; font-size:14px; color:#555555;" style=" margin-top:12px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:14px;">Go to the </span><span style=" font-size:14px; font-weight:600;">Account management setting</span><span style=" font-size:14px;"> of a previous device</span></li> +<li style=" font-family:'Ubuntu'; font-size:14px; color:#555555;" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:14px;">Choose the </span><span style=" font-size:14px; font-weight:600;">Jami account</span><span style=" font-size:14px;"> you want to use</span></li> +<li style=" font-family:'Ubuntu'; font-size:14px; color:#555555;" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:14px;">Go to the </span><span style=" font-size:14px; font-weight:600;">Devices</span><span style=" font-size:14px;"> tab</span></li> +<li style=" font-family:'Ubuntu'; font-size:14px; color:#555555;" style=" margin-top:0px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:14px;">Select </span><span style=" font-size:14px; font-weight:600;">Add a device</span></li></ol> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Ubuntu'; font-size:14px; color:#555555;">You will get the necessary PIN to complete this form. The PIN is only valid for </span><span style=" font-family:'Ubuntu'; font-size:14px; font-weight:600; color:#555555;">10 minutes</span><span style=" font-family:'Ubuntu'; font-size:10px; color:#555555;">.</span></p></body></html> + + + + + Enter your pin: + + + + + Or import a file: + + + + + Link from exported account archive file + + + + + + + (None) + + + + + Password: + كلمة السر: + + + + + Profile + خذ لمحة + + + + + Profile name + + + + + Account + حساب + + + + Register your username. +This will reserve the username so that only you can use it. +Your friends will be able to call you with your usename +instead of using your ID. + + + + + Public username checkbox + + + + + Checkbox selecting if the user wants a public username + + + + + Register public username + سجل اسم المستخدم العام + + + + Public username edit + + + + + Choose your username + اختر اسم مستخدمك + + + + Password text input + + + + + Password text entry + + + + + + Password + كلمة السر + + + + + Password confirmation text input + + + + + Confirm password + + + + + SIP Account + حساب SIP + + + + SIP Server edit + + + + + Server + + + + + SIP proxy input + + + + + SIP proxy text entry + + + + + Proxy + الوكيل + + + + SIP username input + + + + + SIP Password text entry + + + + + Username + اسم المستخدم + + + + + SIP Password text input + + + + + Generating your Jami account… + + + + + Previous page button + + + + + push button to access previous page of wizard + + + + + Previous + + + + + Cancel account create/link + + + + + push button to cancel account creation or linking + + + + + Back + السابق + + + + Next page Button + + + + + Push button to access next page of wizard + + + + + Next + التالي + + + + Open File + فتح ملف + + + + Jami archive files (*.gz); All files (*) + + + + + Your account needs to be migrated. Enter your password. + + + + + Migrating your Jami account... + + + + + Importing account archive... + + + + + Generating your Jami account... + + + + + Generating your SIP account... + + + + + Error creating account + + + + + PasswordDialog + + + Change Account Password + + + + + Enter Current Password + + + + + Enter New Password + + + + + Confirm New Password + + + + + Confirm + + + + + Cancel + ألغِ + + + + Current Password Incorrect + + + + + PhotoBoothDialog + + + Photobooth + + + + + PhotoboothWidget + + + Form + استمارة + + + + Photobooth display + + + + + Choose File + إختار ملف + + + + Image Files (*.jpg *.jpeg *.png) + + + + + PrivateBridging + + + Choose File + إختار ملف + + + + Files (*) + وثائق (*) + + + + QObject + + + No default mail client found + + + + + + Edit Device Name + + + + + Unlink Device From Account + + + + + Save new device name + + + + + Add as contact + + + + + RingButton + + + Select folder + + + + + SettingsWidget + + + Form + استمارة + + + + Settings + إعدادات + + + + Account + حساب + + + + + General + عام + + + + + Audio / Video + + + + + System + النظام + + + + Enable desktop notifications + + + + + Keep minimized on close + أبقي مصغر عند الغلق + + + + Download folder + + + + + Save in + سجل في + + + + Always Recording + + + + + Updates + + + + + Check for updates automatically every + + + + + Interval between update checks in days selector + + + + + days + + + + + Check for updates now button + + + + + Check for updates now + + + + + Password + كلمة السر + + + + + Enable + تفعيل + + + + toggle enable notifications + + + + + Toggle keep minimized on close + + + + + Call Recordings + + + + + Toggle automatic updates + + + + + Jami Account + + + + + + Profile + خذ لمحة + + + + + Identity + + + + + Id + + + + + Registered name + + + + + Type here to register a username + + + + + Register + سجل + + + + Change Password + + + + + Export Account + تصدير الحساب + + + + + Delete Account + + + + + Linked Devices + + + + + Link Another Device + + + + + Banned Contacts + جهات الاتصال المحظورة + + + + Format + + + + + Video device framerate selector + + + + + Preview unavailable + + + + + + Advanced Account Settings + + + + + SIP Account + حساب SIP + + + + Username + اسم المستخدم + + + + Hostname + اسم المضيف + + + + Proxy + الوكيل + + + + Audio + صوت + + + + Microphone + + + + + Audio input device selector + + + + + Output Device + جهاز الإخراج + + + + Choose the output device + + + + + Video + فيديو + + + + Device + جهاز + + + + Video device selector + + + + + A registered name should not have any spaces and must be at least three letters long + + + + + This name is already taken + + + + + + Enter an alias + + + + + Register this name + + + + + Remove Device + + + + + Enter this account's password to confirm the removal of this device + + + + + Are you sure you wish to remove this device? + + + + + Export Account Here + + + + + Select A Folder For Your Downloads + + + + + Select A Folder For Your Recordings + + + + + VideoOverlay + + + Call on Hold + + + + + Hold / Unhold + + + + + Chat + دردشة + + + + Mute Mic + كتم اللاقط + + + + Record call + + + + + Name label + + + + + Time elapsed + + + + + 00:00 + 00:00 + + + + Hangup + أنهي المحادثة + + + + Mute Video + أبكم الفيديو + + + + VideoView + + + Share entire screen + تقاسم كل الشاشة + + + + Share screen area + تقاسم منطقة من الشاشة + + + + Share file + تقاسم الوثيقة + + + \ No newline at end of file diff --git a/translations/ring_client_windows_bg.ts b/translations/ring_client_windows_bg.ts new file mode 100644 index 00000000..78ca4e32 --- /dev/null +++ b/translations/ring_client_windows_bg.ts @@ -0,0 +1,1589 @@ + + + AboutDialog + + + + About + Относно + + + + about button + + + + + credits button + + + + + Credits + Заслуги + + + + Free as in Freedom + + + + + The Microsoft Windows client for Jami. +Jami is a secured and distributed communication software. + + + + + version + версия + + + + Created by: + Създаден от: + + + + Artwork by: + С изображения от: + + + + Based on the SFLPhone project + Основан на проекта „SFLPhone“ + + + + AccountItemDelegate + + + Add Account + + + + + AdvancedSIPSettingsWidget + + + Form + От + + + + Call Settings + + + + + Auto Answer Calls + + + + + Enable Custom Ringtone + + + + + Connectivity + + + + + STUN Address + + + + + Use STUN + Използване на STUN + + + + Use UPnP + + + + + Use TURN + Използване на TURN + + + + TURN Password + + + + + TURN Username + + + + + TURN Address + + + + + Media + Звук и видео + + + + Enable Video + Активиране на видео + + + + Video Codecs + Видео кодеци + + + + Audio Codecs + + + + + Audio Files (*.wav *.ogg *.opus *.mp3 *aiff *wma) + + + + + Add a custom ringtone + + + + + AdvancedSettingsWidget + + + Form + От + + + + Call Settings + + + + + Allow Calls From Untrusted Peers + + + + + Auto Answer Calls + + + + + Enable Custom Ringtone + + + + + Add a custom ringtone + + + + + Name Server + + + + + Address + Адрес + + + + OpenDHT Configuration + + + + + Enable Proxy + + + + + Bootstrap + Начална установка + + + + Security + Сигурност + + + + Private Key Password + Парола за частен ключ + + + + User Certificate + Потребителски сертификат + + + + Private Key + + + + + CA Certificate + + + + + Connectivity + + + + + Use STUN + Използване на STUN + + + + STUN Address + + + + + Use UPnP + + + + + Use TURN + Използване на TURN + + + + TURN Password + + + + + TURN Username + + + + + TURN Address + + + + + Media + Звук и видео + + + + Enable Video + Активиране на видео + + + + Audio Codecs + + + + + Video Codecs + Видео кодеци + + + + Audio Files (*.wav *.ogg *.opus *.mp3 *aiff *wma) + + + + + AnimatedOverlay + + + Form + От + + + + BannedItemWidget + + + Form + От + + + + name + + + + + id + + + + + CallWidget + + + Show conversations + + + + + Conversations + Разговори + + + + Search contact text input + + + + + Jami is free software for universal communication which respects the freedoms and privacy of its users. + Ring е безплатен софтуер за универсална комуникация, който уважава свободата и личните данни на потребителите си. + + + + + This is your ID. +Copy and share it with your friends! + + + + + + Show ring ID QR code + + + + + Share ring ID button + + + + + Double-click to copy + + + + + Error while generating QR Code + Грешка при създаването на QR-код + + + + + best name + + + + + best Id + + + + + Back to homepage button + + + + + Add to contacts + Добавяне към контактите + + + + Show invites + + + + + Invites + + + + + + Find a new or existing contact + + + + + Wants to talk to you! + Желае да говори с Вас! + + + + Answer incoming call button + + + + + Ignore incoming call button + + + + + Answer + Отговор + + + + Ignore + Игнориране + + + + Cancel outgoing call + + + + + Cancel + Отказ + + + + Start video call + Започване на видео разговор + + + + Start audio call + Започване на гласов разговор + + + + Clear conversation + Изчистване на разговора + + + + Remove contact + + + + + Block contact + Блокиране на контакт + + + + Copy number + Копиране на номера + + + + Search your received invitations + + + + + Contact me on Jami + + + + + My Id is : + + + + + %1 + %1 is the contact username + %1 + + + + %1 + %1 is the contact unique identifier + %1 + + + + Call incoming from %1 + Входящо повикване от %1 + + + + DeleteAccountDialog + + + Account deletion + + + + + Do you really want to delete the following account? + + + + + If this account hasn't been exported, or added to another device, it will be irrevocably lost. + + + + + Permanently delete account + + + + + Delete + Изтриване + + + + Cancel account deletion + + + + + Cancel + Отказ + + + + DeviceItemWidget + + + Form + От + + + + Device Id + + + + + this device + това устройство + + + + InviteButtonsWidget + + + Accept + Приемане + + + + Refuse + Отказ + + + + Block + Блокиране + + + + LinkDeviceDialog + + + Dialog + Прозорец + + + + Enter your account password + + + + + Password + Парола + + + + Ok + Добре + + + + Cancel + Отказ + + + + Exporting account + Изнасяне на акаунта + + + + Your PIN is + + + + + PIN + ПИН + + + + This pin and the account password should be entered in your device within 10 minutes. + + + + + Close + Затваряне + + + + Link Another Device + + + + + Incorrect password + + + + + Something went wrong. +Please try again later. + + + + + MainWindow + + + Settings + Настройки + + + + Exit + Изход + + + + About + Относно + + + + Jami + + + + + NameRegistrationDialog + + + Set Registered Name + + + + + Enter your account password + + + + + Password text input + + + + + Password text entry + + + + + Password + Парола + + + + Register + Регистриране + + + + Cancel + Отказ + + + + Registering Name + + + + + Something went wrong + + + + + Close + Затваряне + + + + Incorrect password + + + + + Network error + Мрежова грешка + + + + NewWizardWidget + + + Form + От + + + + Welcome Label + + + + + Welcome to + + + + + Welcome Logo + + + + + Create Jami account button + + + + + Push button for Jami account creation start trigger + + + + + Create a Jami account + Създаване на профил в Jami + + + + Link device button + + + + + Push button for device linkage start trigger + + + + + Link this device to an account + Свързване на това устройство с акаунт + + + + Create Jami SIP account button + + + + + Push button for Jami SIP account creation start trigger + + + + + Create a SIP account + + + + + Link this device to an existing account + Свържи това устройство със съществуващ акаунт + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Ubuntu'; font-size:14px; color:#555555;">To link this device to another account, you first </span><span style=" font-family:'Ubuntu'; font-size:14px; font-weight:600; color:#555555;">need to obtain a PIN</span><span style=" font-family:'Ubuntu'; font-size:14px; color:#555555;"> code. To generate the PIN code:</span></p> +<ol style="margin-top: 0px; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; -qt-list-indent: 1;"><li style=" font-family:'Ubuntu'; font-size:14px; color:#555555;" style=" margin-top:12px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:14px;">Go to the </span><span style=" font-size:14px; font-weight:600;">Account management setting</span><span style=" font-size:14px;"> of a previous device</span></li> +<li style=" font-family:'Ubuntu'; font-size:14px; color:#555555;" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:14px;">Choose the </span><span style=" font-size:14px; font-weight:600;">Jami account</span><span style=" font-size:14px;"> you want to use</span></li> +<li style=" font-family:'Ubuntu'; font-size:14px; color:#555555;" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:14px;">Go to the </span><span style=" font-size:14px; font-weight:600;">Devices</span><span style=" font-size:14px;"> tab</span></li> +<li style=" font-family:'Ubuntu'; font-size:14px; color:#555555;" style=" margin-top:0px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:14px;">Select </span><span style=" font-size:14px; font-weight:600;">Add a device</span></li></ol> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Ubuntu'; font-size:14px; color:#555555;">You will get the necessary PIN to complete this form. The PIN is only valid for </span><span style=" font-family:'Ubuntu'; font-size:14px; font-weight:600; color:#555555;">10 minutes</span><span style=" font-family:'Ubuntu'; font-size:10px; color:#555555;">.</span></p></body></html> + + + + + Enter your pin: + + + + + Or import a file: + + + + + Link from exported account archive file + + + + + + + (None) + + + + + Password: + Парола: + + + + + Profile + Профил + + + + + Profile name + + + + + Account + Акаунт + + + + Register your username. +This will reserve the username so that only you can use it. +Your friends will be able to call you with your usename +instead of using your ID. + + + + + Public username checkbox + + + + + Checkbox selecting if the user wants a public username + + + + + Register public username + Регистриране на публично потребителско име + + + + Public username edit + + + + + Choose your username + Изберете потребителско име + + + + Password text input + + + + + Password text entry + + + + + + Password + Парола + + + + + Password confirmation text input + + + + + Confirm password + Потвърдете паролата + + + + SIP Account + Акаунт за SIP + + + + SIP Server edit + + + + + Server + + + + + SIP proxy input + + + + + SIP proxy text entry + + + + + Proxy + Прокси + + + + SIP username input + + + + + SIP Password text entry + + + + + Username + Потребителско име + + + + + SIP Password text input + + + + + Generating your Jami account… + + + + + Previous page button + + + + + push button to access previous page of wizard + + + + + Previous + Предишен + + + + Cancel account create/link + + + + + push button to cancel account creation or linking + + + + + Back + Назад + + + + Next page Button + + + + + Push button to access next page of wizard + + + + + Next + Напред + + + + Open File + Отваряне на файл + + + + Jami archive files (*.gz); All files (*) + + + + + Your account needs to be migrated. Enter your password. + + + + + Migrating your Jami account... + + + + + Importing account archive... + + + + + Generating your Jami account... + + + + + Generating your SIP account... + + + + + Error creating account + Грешка при създаването на акаунта + + + + PasswordDialog + + + Change Account Password + + + + + Enter Current Password + + + + + Enter New Password + + + + + Confirm New Password + + + + + Confirm + + + + + Cancel + Отказ + + + + Current Password Incorrect + + + + + PhotoBoothDialog + + + Photobooth + + + + + PhotoboothWidget + + + Form + От + + + + Photobooth display + + + + + Choose File + Изберете файл + + + + Image Files (*.jpg *.jpeg *.png) + + + + + PrivateBridging + + + Choose File + Изберете файл + + + + Files (*) + Всички файлове (*) + + + + QObject + + + No default mail client found + Не е открит клиент за е-поща по подразбиране + + + + + Edit Device Name + + + + + Unlink Device From Account + + + + + Save new device name + + + + + Add as contact + + + + + RingButton + + + Select folder + + + + + SettingsWidget + + + Form + От + + + + Settings + Настройки + + + + Account + Акаунт + + + + + General + Общи + + + + + Audio / Video + + + + + System + Система + + + + Enable desktop notifications + + + + + Keep minimized on close + Минимизиране при затваряне + + + + Download folder + + + + + Save in + Запазване в + + + + Always Recording + + + + + Updates + + + + + Check for updates automatically every + + + + + Interval between update checks in days selector + + + + + days + + + + + Check for updates now button + + + + + Check for updates now + + + + + Password + Парола + + + + + Enable + + + + + toggle enable notifications + + + + + Toggle keep minimized on close + + + + + Call Recordings + + + + + Toggle automatic updates + + + + + Jami Account + + + + + + Profile + Профил + + + + + Identity + + + + + Id + + + + + Registered name + Регистрирано име + + + + Type here to register a username + + + + + Register + Регистриране + + + + Change Password + Промяна на паролата + + + + Export Account + + + + + + Delete Account + + + + + Linked Devices + + + + + Link Another Device + + + + + Banned Contacts + Блокирани контакти + + + + Format + + + + + Video device framerate selector + + + + + Preview unavailable + + + + + + Advanced Account Settings + + + + + SIP Account + Акаунт за SIP + + + + Username + Потребителско име + + + + Hostname + Име на сървъра + + + + Proxy + Прокси + + + + Audio + Звук + + + + Microphone + + + + + Audio input device selector + + + + + Output Device + Изходящо устройство + + + + Choose the output device + + + + + Video + Видео + + + + Device + Устройство + + + + Video device selector + + + + + A registered name should not have any spaces and must be at least three letters long + + + + + This name is already taken + + + + + + Enter an alias + + + + + Register this name + + + + + Remove Device + + + + + Enter this account's password to confirm the removal of this device + + + + + Are you sure you wish to remove this device? + + + + + Export Account Here + + + + + Select A Folder For Your Downloads + + + + + Select A Folder For Your Recordings + + + + + VideoOverlay + + + Call on Hold + Задържан разговор + + + + Hold / Unhold + Задържане / подновяване + + + + Chat + Съобщения + + + + Mute Mic + Заглушаване на микрофона + + + + Record call + + + + + Name label + Етикет за името + + + + Time elapsed + Изминало време + + + + 00:00 + 00:00 + + + + Hangup + Затваряне + + + + Mute Video + Заглушаване на видеото + + + + VideoView + + + Share entire screen + Споделяне на целия екран + + + + Share screen area + Споделяне на област от екрана + + + + Share file + Споделяне на файл + + + \ No newline at end of file diff --git a/translations/ring_client_windows_ca.ts b/translations/ring_client_windows_ca.ts new file mode 100644 index 00000000..bf8c6851 --- /dev/null +++ b/translations/ring_client_windows_ca.ts @@ -0,0 +1,1605 @@ + + + AboutDialog + + + + About + Quant a + + + + about button + botó quant a + + + + credits button + botó de crèdits + + + + Credits + Crèdits + + + + Free as in Freedom + Free as in Freedom + + + + The Microsoft Windows client for Jami. +Jami is a secured and distributed communication software. + El client de Microsoft Windows per a Jami. +Ring és un programari de comunicació segur i distribuït. + + + + version + versió + + + + Created by: + Programat per: + + + + Artwork by: + Art fet per: + + + + Based on the SFLPhone project + Basat en el projecte SFLPhone + + + + AccountItemDelegate + + + Add Account + Afegeix compte + + + + AdvancedSIPSettingsWidget + + + Form + Formulari + + + + Call Settings + Preferències de trucada + + + + Auto Answer Calls + Respon trucades automàticament + + + + Enable Custom Ringtone + Habilita to de trucada personalitzat + + + + Connectivity + Connectivitat + + + + STUN Address + Adreça STUN + + + + Use STUN + Utilitza STUN + + + + Use UPnP + Utilitza UPnP + + + + Use TURN + Utilitza TURN + + + + TURN Password + Contrasenya de TURN + + + + TURN Username + Usuari de TURN + + + + TURN Address + Adreça TURN + + + + Media + Mitjans + + + + Enable Video + Habilita el vídeo + + + + Video Codecs + Còdecs de vídeo + + + + Audio Codecs + Còdecs d'àudio + + + + Audio Files (*.wav *.ogg *.opus *.mp3 *aiff *wma) + Fitxers d'àudio (*.wav *.ogg *.opus *.mp3 *aiff *wma) + + + + Add a custom ringtone + Afegeix un to de trucada personalitzat + + + + AdvancedSettingsWidget + + + Form + Formulari + + + + Call Settings + Preferències de trucada + + + + Allow Calls From Untrusted Peers + Permet trucades de contactes desconeguts + + + + Auto Answer Calls + Respon trucades automàticament + + + + Enable Custom Ringtone + Habilita to de trucada personalitzat + + + + Add a custom ringtone + Afegeix un to de trucada personalitzat + + + + Name Server + Servidor de noms + + + + Address + Adreça + + + + OpenDHT Configuration + Configuració de OpenDHT + + + + Enable Proxy + Habilita servidor intermediari + + + + Bootstrap + Bootstrap + + + + Security + Seguretat + + + + Private Key Password + Contrasenya de la clau privada + + + + User Certificate + Certificat d'usuari + + + + Private Key + Clau privada + + + + CA Certificate + Certificat CA + + + + Connectivity + Connectivitat + + + + Use STUN + Utilitza STUN + + + + STUN Address + Adreça STUN + + + + Use UPnP + Utilitza UPnP + + + + Use TURN + Utilitza TURN + + + + TURN Password + Contrasenya de TURN + + + + TURN Username + Usuari de TURN + + + + TURN Address + Adreça TURN + + + + Media + Mitjans + + + + Enable Video + Habilita el vídeo + + + + Audio Codecs + Còdecs d'àudio + + + + Video Codecs + Còdecs de vídeo + + + + Audio Files (*.wav *.ogg *.opus *.mp3 *aiff *wma) + Fitxers d'àudio (*.wav *.ogg *.opus *.mp3 *aiff *wma) + + + + AnimatedOverlay + + + Form + Formulari + + + + BannedItemWidget + + + Form + Formulari + + + + name + nom + + + + id + id + + + + CallWidget + + + Show conversations + Mostra converses + + + + Conversations + Converses + + + + Search contact text input + Cerca text del contacte + + + + Jami is free software for universal communication which respects the freedoms and privacy of its users. + Jami és un programari lliure de comunicació universal, que respecta les llibertats i la privacitat dels seus usuaris. + + + + + This is your ID. +Copy and share it with your friends! + + +Aquest és el seu ID. +Copiï'l i comparteixi'l amb els seus amics! + + + + Show ring ID QR code + Mostra codi QR de ring + + + + Share ring ID button + Botó de compartició de ID de ring + + + + Double-click to copy + Doble clic per copiar + + + + Error while generating QR Code + Error al generar el codi QR + + + + + best name + millor nom + + + + best Id + millor Id + + + + Back to homepage button + Botó per tornar a la pàgina principal + + + + Add to contacts + Afegir als contactes + + + + Show invites + Mostra invitacions + + + + Invites + Invitacions + + + + + Find a new or existing contact + Troba un contacte nou o existent + + + + Wants to talk to you! + Vol parlar amb tu! + + + + Answer incoming call button + Botó per respondre trucada entrant + + + + Ignore incoming call button + Botó per ignorar trucada entrant + + + + Answer + Respon + + + + Ignore + Ignora + + + + Cancel outgoing call + Canceŀla trucada sortint + + + + Cancel + Canceŀla + + + + Start video call + Comença una videotrucada + + + + Start audio call + Comença una trucada de veu. + + + + Clear conversation + Neteja la conversa + + + + Remove contact + Elimina el contacte + + + + Block contact + Bloqueja el contacte + + + + Copy number + Copia el número + + + + Search your received invitations + Cerca les invitacions rebudes + + + + Contact me on Jami + Contacta amb mi a Jami + + + + My Id is : + El meu Id és: + + + + %1 + %1 is the contact username + %1 + + + + %1 + %1 is the contact unique identifier + %1 + + + + Call incoming from %1 + Trucada entrant de %1 + + + + DeleteAccountDialog + + + Account deletion + Eliminació de compte + + + + Do you really want to delete the following account? + Esteu segur que voleu esborrar el compte? + + + + If this account hasn't been exported, or added to another device, it will be irrevocably lost. + Si aquest compte no s'ha exportat o afegit a un altre dispositiu, es perdrà irremeiablement. + + + + Permanently delete account + Elimina el compte de forma permanent + + + + Delete + Suprimeix + + + + Cancel account deletion + Canceŀla l'eliminació del compte + + + + Cancel + Cancel·la + + + + DeviceItemWidget + + + Form + Formulari + + + + Device Id + Id del dispositiu + + + + this device + aquest dispositiu + + + + InviteButtonsWidget + + + Accept + Accepta + + + + Refuse + Rebutja + + + + Block + Bloca + + + + LinkDeviceDialog + + + Dialog + Diàleg + + + + Enter your account password + Inseriu la contrasenya del vostre compte + + + + Password + Contrasenya + + + + Ok + D'acord + + + + Cancel + Cancel·la + + + + Exporting account + Exportant compte + + + + Your PIN is + El vostre PIN és + + + + PIN + PIN + + + + This pin and the account password should be entered in your device within 10 minutes. + Aquest PIN i la contrasenya del compte tindrien que introduir-se en el vostre dispositiu en un màxim de 10 minuts. + + + + Close + Tanca + + + + Link Another Device + Vincula un altre dispositiu + + + + Incorrect password + Contrasenya incorrecta + + + + Something went wrong. +Please try again later. + Alguna cosa ha anat malament. +Si us plau, torni ha intentar-ho més tard. + + + + MainWindow + + + Settings + Opcions + + + + Exit + Sortir + + + + About + Quant a + + + + Jami + Jami + + + + NameRegistrationDialog + + + Set Registered Name + Estableix nom registrat + + + + Enter your account password + Inseriu la contrasenya del vostre compte + + + + Password text input + Entrada de text de la contrasenya + + + + Password text entry + Entrada de text de la contrasenya + + + + Password + Contrasenya + + + + Register + Registra + + + + Cancel + Cancel·la + + + + Registering Name + Registrant nom d'usuari + + + + Something went wrong + Alguna cosa ha anat malament + + + + Close + Tanca + + + + Incorrect password + Contrasenya incorrecta + + + + Network error + Error de xarxa + + + + NewWizardWidget + + + Form + Formulari + + + + Welcome Label + Etiqueta de Benvinguda + + + + Welcome to + Benvingut a + + + + Welcome Logo + Logo de Benvinguda + + + + Create Jami account button + Botó de creació de compte Jami + + + + Push button for Jami account creation start trigger + Botó per al disparador d'inici de la creació de compte Jami + + + + Create a Jami account + Crear un compte Jami + + + + Link device button + Botó de vinculació de dispositiu + + + + Push button for device linkage start trigger + Botó per al disparador d'inici de vinculació de dispositiu + + + + Link this device to an account + Enllaça aquest dispositiu a un compte + + + + Create Jami SIP account button + Botó de creació de compte Jami SIP + + + + Push button for Jami SIP account creation start trigger + Botó per al disparador d'inici de creació de compte Jami SIP + + + + Create a SIP account + Crea un compte SIP + + + + Link this device to an existing account + Enllaça aquest dispositiu a un compte ja existent + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Ubuntu'; font-size:14px; color:#555555;">To link this device to another account, you first </span><span style=" font-family:'Ubuntu'; font-size:14px; font-weight:600; color:#555555;">need to obtain a PIN</span><span style=" font-family:'Ubuntu'; font-size:14px; color:#555555;"> code. To generate the PIN code:</span></p> +<ol style="margin-top: 0px; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; -qt-list-indent: 1;"><li style=" font-family:'Ubuntu'; font-size:14px; color:#555555;" style=" margin-top:12px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:14px;">Go to the </span><span style=" font-size:14px; font-weight:600;">Account management setting</span><span style=" font-size:14px;"> of a previous device</span></li> +<li style=" font-family:'Ubuntu'; font-size:14px; color:#555555;" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:14px;">Choose the </span><span style=" font-size:14px; font-weight:600;">Jami account</span><span style=" font-size:14px;"> you want to use</span></li> +<li style=" font-family:'Ubuntu'; font-size:14px; color:#555555;" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:14px;">Go to the </span><span style=" font-size:14px; font-weight:600;">Devices</span><span style=" font-size:14px;"> tab</span></li> +<li style=" font-family:'Ubuntu'; font-size:14px; color:#555555;" style=" margin-top:0px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:14px;">Select </span><span style=" font-size:14px; font-weight:600;">Add a device</span></li></ol> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Ubuntu'; font-size:14px; color:#555555;">You will get the necessary PIN to complete this form. The PIN is only valid for </span><span style=" font-family:'Ubuntu'; font-size:14px; font-weight:600; color:#555555;">10 minutes</span><span style=" font-family:'Ubuntu'; font-size:10px; color:#555555;">.</span></p></body></html> + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Ubuntu'; font-size:14px; color:#555555;">Per a vincular aquest dispositiu a un altre compte, primer has </span><span style=" font-family:'Ubuntu'; font-size:14px; font-weight:600; color:#555555;">d'obtenir un codi PIN</span><span style=" font-family:'Ubuntu'; font-size:14px; color:#555555;">. Per a generar un codi PIN:</span></p> +<ol style="margin-top: 0px; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; -qt-list-indent: 1;"><li style=" font-family:'Ubuntu'; font-size:14px; color:#555555;" style=" margin-top:12px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:14px;">Vés a </span><span style=" font-size:14px; font-weight:600;">opcions de gestió del compte</span><span style=" font-size:14px;"> d'un dispositiu anterior</span></li> +<li style=" font-family:'Ubuntu'; font-size:14px; color:#555555;" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:14px;">Escull un </span><span style=" font-size:14px; font-weight:600;">compte Jami</span><span style=" font-size:14px;"> que vulguis utilitzar</span></li> +<li style=" font-family:'Ubuntu'; font-size:14px; color:#555555;" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:14px;">Vés a la pestanya</span><span style=" font-size:14px; font-weight:600;">Dispositius</span></li> +<li style=" font-family:'Ubuntu'; font-size:14px; color:#555555;" style=" margin-top:0px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:14px;">Selecciona</span><span style=" font-size:14px; font-weight:600;">Afegeix un dispositiu</span></li></ol> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Ubuntu'; font-size:14px; color:#555555;">Obtindràs el PIN necessari per completar aquest formulari. El PIN només és vàlid durant </span><span style=" font-family:'Ubuntu'; font-size:14px; font-weight:600; color:#555555;">10 minuts</span><span style=" font-family:'Ubuntu'; font-size:10px; color:#555555;">.</span></p></body></html> + + + + Enter your pin: + Entra el pin: + + + + Or import a file: + O importa un fitxer: + + + + Link from exported account archive file + Vincula des d'un compte exportat a un fitxer d'arxiu + + + + + + (None) + (Cap) + + + + Password: + Contrasenya: + + + + + Profile + Perfil + + + + + Profile name + Nom de perfil + + + + Account + Compte + + + + Register your username. +This will reserve the username so that only you can use it. +Your friends will be able to call you with your usename +instead of using your ID. + Registra el teu nom d'usuari. +Es reservarà el nom d'usuari de forma que només vostè pugui utilitzar-lo. +Els seus amics podran trucar-lo amb el vostre nom d'usuari +en comptes d'utilitzar el vostre ID. + + + + Public username checkbox + Capsa de verificació de nom d'usuari públic + + + + Checkbox selecting if the user wants a public username + Capsa de verificació seleccionant si l'usuari vol un nom d'usuari públic + + + + Register public username + Registra nom d'usuari públic + + + + Public username edit + Edició de nom d'usuari públic + + + + Choose your username + Esculli el vostre nom d'usuari + + + + Password text input + Entrada de text de la contrasenya + + + + Password text entry + Entrada de text de la contrasenya + + + + + Password + Contrasenya + + + + + Password confirmation text input + Entrada de text de confirmació de contrasenya + + + + Confirm password + Confirmi contrasenya + + + + SIP Account + Compte SIP + + + + SIP Server edit + Edició de servidor SIP + + + + Server + Servidor + + + + SIP proxy input + Entrada de servidor intermediari SIP + + + + SIP proxy text entry + Entrada de text de servidor intermediari SIP + + + + Proxy + Intermediari + + + + SIP username input + Entrada de nom d'usuari SIP + + + + SIP Password text entry + Entrada de text de contraseña SIP + + + + Username + Nom d'usuari + + + + + SIP Password text input + Entrada de text de contraseña SIP + + + + Generating your Jami account… + Generant el seu compte Jami… + + + + Previous page button + Botó de pàgina anterior + + + + push button to access previous page of wizard + Botó per accedir a la pàgina anterior de l'assistent + + + + Previous + Previ + + + + Cancel account create/link + Canceŀla creació/vinculació de compte + + + + push button to cancel account creation or linking + Botó per a canceŀlar la creació o vinculació del compte + + + + Back + Enrere + + + + Next page Button + Botó següent pàgina + + + + Push button to access next page of wizard + Botó per accedir a la pàgina següent de l'assistent + + + + Next + Endavant + + + + Open File + Obre fitxer + + + + Jami archive files (*.gz); All files (*) + Arxius Jami (*.gz); Tots els fitxers (*) + + + + Your account needs to be migrated. Enter your password. + El vostre compte s'ha de migrar. Inseriu la vostra contrasenya + + + + Migrating your Jami account... + Migrant el teu compte Jami… + + + + Importing account archive... + Important l'arxiu del compte… + + + + Generating your Jami account... + Generant el seu compte Jami… + + + + Generating your SIP account... + Generant el seu compte SIP… + + + + Error creating account + Error al crear el compte + + + + PasswordDialog + + + Change Account Password + Canvia la contrasenya del compte + + + + Enter Current Password + Inseriu la contrasenya actual + + + + Enter New Password + Inseriu la nova contrasenya + + + + Confirm New Password + Confirmi la nova contrasenya + + + + Confirm + Confirma + + + + Cancel + Cancel·la + + + + Current Password Incorrect + Contrasenya actual incorrecta + + + + PhotoBoothDialog + + + Photobooth + Galeria de fotos + + + + PhotoboothWidget + + + Form + Formulari + + + + Photobooth display + Vista de la galeria de fotos + + + + Choose File + Esculli un fitxer + + + + Image Files (*.jpg *.jpeg *.png) + Fitxers d'imatge (*.jpg *.jpeg *.png) + + + + PrivateBridging + + + Choose File + Esculli un fitxer + + + + Files (*) + Fitxers (*) + + + + QObject + + + No default mail client found + No s'ha detectat cap client de correu electrònic + + + + + Edit Device Name + Editar nom de dispositiu + + + + Unlink Device From Account + Desvincula dispositiu del compte + + + + Save new device name + Desa el nou nom de dispositiu + + + + Add as contact + Afegir com a contacte + + + + RingButton + + + Select folder + Esculli carpeta + + + + SettingsWidget + + + Form + Formulari + + + + Settings + Opcions + + + + Account + Compte + + + + + General + General + + + + + Audio / Video + Àudio / Vídeo + + + + System + Sistema + + + + Enable desktop notifications + Habilitar notificacions d'escriptori + + + + Keep minimized on close + Manté minimitzat al tancar + + + + Download folder + Descarrega carpeta + + + + Save in + Desa a + + + + Always Recording + Sempre enregistrant + + + + Updates + Actualitzacions + + + + Check for updates automatically every + Comprova actualitzacions cada + + + + Interval between update checks in days selector + Selector d'interval entre comprovacions d'actualitzacions + + + + days + dies + + + + Check for updates now button + Botó de comprovació immediata d'actualitzacions + + + + Check for updates now + Comprova actualitzacions immediatament + + + + Password + Contrasenya + + + + + Enable + Habilita + + + + toggle enable notifications + Commuta habilitar notificacions + + + + Toggle keep minimized on close + Commuta mantenir minimitzat al tancar + + + + Call Recordings + Enregistraments de trucades + + + + Toggle automatic updates + Commuta actualitzacions automàtiques + + + + Jami Account + Compte Jami + + + + + Profile + Perfil + + + + + Identity + Identitat + + + + Id + Id + + + + Registered name + Nom registrat + + + + Type here to register a username + Escrigui aquí per registrar un nom d'usuari + + + + Register + Registra + + + + Change Password + Canvia la contrasenya + + + + Export Account + Exporta el compte + + + + + Delete Account + Esborrar compte + + + + Linked Devices + Dispositius vinculats + + + + Link Another Device + Vincula un altre dispositiu + + + + Banned Contacts + Contactes blocats + + + + Format + Formata + + + + Video device framerate selector + Selector de taxa de fotogrames del dispositiu de vídeo + + + + Preview unavailable + Previsualització no disponible + + + + + Advanced Account Settings + Preferències avançades del compte + + + + SIP Account + Compte SIP + + + + Username + Nom d'usuari + + + + Hostname + Nom d'amfitrió + + + + Proxy + Intermediari + + + + Audio + Àudio + + + + Microphone + Micròfon + + + + Audio input device selector + Selector de dispositiu d'entrada d'àudio + + + + Output Device + Dispositiu de sortida + + + + Choose the output device + Esculli dispositiu de sortida + + + + Video + Vídeo + + + + Device + Dispositiu + + + + Video device selector + Selector de dispositiu de vídeo + + + + A registered name should not have any spaces and must be at least three letters long + Un nom registrat no pot tenir espais i ha de tenir una longitud mínima de tres caràcters + + + + This name is already taken + Aquest nom ja està registrat + + + + + Enter an alias + Inseriu un alias + + + + Register this name + Registri aquest nom + + + + Remove Device + Elimini el dispositiu + + + + Enter this account's password to confirm the removal of this device + Insereix la contrasenya d'aquest compte per confirmar l'eliminació d'aquest dispositiu + + + + Are you sure you wish to remove this device? + Esteu segur que voleu eliminar aquest dispositiu? + + + + Export Account Here + Exporta el compte aquí + + + + Select A Folder For Your Downloads + Seleccioni una carpeta per les seves descàrregues + + + + Select A Folder For Your Recordings + Seleccioni una carpeta per als seus enregistraments + + + + VideoOverlay + + + Call on Hold + Trucada en espera + + + + Hold / Unhold + Reté / Allibera + + + + Chat + Xat + + + + Mute Mic + Silencia el micròfon + + + + Record call + Enregistra trucada + + + + Name label + Etiqueta de nom + + + + Time elapsed + Temps transcorregut + + + + 00:00 + 00:00 + + + + Hangup + Penjar + + + + Mute Video + Silencia el vídeo + + + + VideoView + + + Share entire screen + Comparteix tota la pantalla + + + + Share screen area + Compartir pantalla + + + + Share file + Compartir arxiu + + + \ No newline at end of file diff --git a/translations/ring_client_windows_cs_CZ.ts b/translations/ring_client_windows_cs_CZ.ts new file mode 100644 index 00000000..5c0e9d1b --- /dev/null +++ b/translations/ring_client_windows_cs_CZ.ts @@ -0,0 +1,1590 @@ + + + AboutDialog + + + + About + O aplikaci + + + + about button + O + + + + credits button + Zásluhy + + + + Credits + Zásluhy + + + + Free as in Freedom + + + + + The Microsoft Windows client for Jami. +Jami is a secured and distributed communication software. + Klient Microsoft Windows pro Jami. +Jami je bezpečný a distribuovaný komunikační program. + + + + version + verze + + + + Created by: + Vytvořili: + + + + Artwork by: + Grafika: + + + + Based on the SFLPhone project + Postaveno na projektu SFLPhone + + + + AccountItemDelegate + + + Add Account + + + + + AdvancedSIPSettingsWidget + + + Form + Formulář + + + + Call Settings + + + + + Auto Answer Calls + + + + + Enable Custom Ringtone + + + + + Connectivity + Připojení + + + + STUN Address + + + + + Use STUN + Použít STUN + + + + Use UPnP + + + + + Use TURN + Použít TURN + + + + TURN Password + + + + + TURN Username + + + + + TURN Address + + + + + Media + Média + + + + Enable Video + Povolit video + + + + Video Codecs + Obrazové kodeky + + + + Audio Codecs + Zvukové kodeky + + + + Audio Files (*.wav *.ogg *.opus *.mp3 *aiff *wma) + + + + + Add a custom ringtone + + + + + AdvancedSettingsWidget + + + Form + Formulář + + + + Call Settings + + + + + Allow Calls From Untrusted Peers + + + + + Auto Answer Calls + + + + + Enable Custom Ringtone + + + + + Add a custom ringtone + + + + + Name Server + Název serveru + + + + Address + Adresa + + + + OpenDHT Configuration + + + + + Enable Proxy + Povolit proxy + + + + Bootstrap + Bootstrap + + + + Security + Zabezpečení + + + + Private Key Password + Heslo soukromého klíče + + + + User Certificate + Uživatelský certifikát + + + + Private Key + + + + + CA Certificate + + + + + Connectivity + Připojení + + + + Use STUN + Použít STUN + + + + STUN Address + + + + + Use UPnP + + + + + Use TURN + Použít TURN + + + + TURN Password + + + + + TURN Username + + + + + TURN Address + + + + + Media + Média + + + + Enable Video + Povolit video + + + + Audio Codecs + Zvukové kodeky + + + + Video Codecs + Obrazové kodeky + + + + Audio Files (*.wav *.ogg *.opus *.mp3 *aiff *wma) + + + + + AnimatedOverlay + + + Form + Formulář + + + + BannedItemWidget + + + Form + Formulář + + + + name + + + + + id + + + + + CallWidget + + + Show conversations + + + + + Conversations + Konverzace + + + + Search contact text input + + + + + Jami is free software for universal communication which respects the freedoms and privacy of its users. + Jami je svobodný software určený k univerzální komunikaci, který respektuje svobody a práva uživatelů. + + + + + This is your ID. +Copy and share it with your friends! + + + + + + Show ring ID QR code + + + + + Share ring ID button + + + + + Double-click to copy + Dvakrát klepněte pro kopírování + + + + Error while generating QR Code + Chyba při vytváření QR kódu + + + + + best name + + + + + best Id + + + + + Back to homepage button + + + + + Add to contacts + Přidat do kontaktů + + + + Show invites + Ukázat pozvání + + + + Invites + + + + + + Find a new or existing contact + + + + + Wants to talk to you! + Chce s vámi hovořit! + + + + Answer incoming call button + + + + + Ignore incoming call button + + + + + Answer + Přijmout + + + + Ignore + Přehlížet + + + + Cancel outgoing call + + + + + Cancel + Zrušit + + + + Start video call + + + + + Start audio call + + + + + Clear conversation + + + + + Remove contact + + + + + Block contact + Blokovat kontakt + + + + Copy number + Zkopírovat číslo + + + + Search your received invitations + + + + + Contact me on Jami + + + + + My Id is : + + + + + %1 + %1 is the contact username + %1 + + + + %1 + %1 is the contact unique identifier + %1 + + + + Call incoming from %1 + Příchozí hovor od %1 + + + + DeleteAccountDialog + + + Account deletion + + + + + Do you really want to delete the following account? + + + + + If this account hasn't been exported, or added to another device, it will be irrevocably lost. + + + + + Permanently delete account + + + + + Delete + Odstranit + + + + Cancel account deletion + + + + + Cancel + Zrušit + + + + DeviceItemWidget + + + Form + Formulář + + + + Device Id + + + + + this device + toto zařízení + + + + InviteButtonsWidget + + + Accept + Přijmout + + + + Refuse + Odmítnout + + + + Block + Blokovat + + + + LinkDeviceDialog + + + Dialog + Dialog + + + + Enter your account password + + + + + Password + Heslo + + + + Ok + OK + + + + Cancel + Zrušit + + + + Exporting account + Exportuji účet + + + + Your PIN is + + + + + PIN + PIN + + + + This pin and the account password should be entered in your device within 10 minutes. + + + + + Close + Zavřít + + + + Link Another Device + Připojit další zařízení + + + + Incorrect password + Nesprávné heslo + + + + Something went wrong. +Please try again later. + + + + + MainWindow + + + Settings + Nastavení + + + + Exit + Odejít + + + + About + O aplikaci + + + + Jami + Jami + + + + NameRegistrationDialog + + + Set Registered Name + Nastavit registrované jméno + + + + Enter your account password + + + + + Password text input + Zadání textu hesla + + + + Password text entry + Zadání textu hesla + + + + Password + Heslo + + + + Register + Zaregistrovat + + + + Cancel + Zrušit + + + + Registering Name + + + + + Something went wrong + + + + + Close + Zavřít + + + + Incorrect password + Nesprávné heslo + + + + Network error + Chyba sítě + + + + NewWizardWidget + + + Form + Formulář + + + + Welcome Label + + + + + Welcome to + Vítejte v + + + + Welcome Logo + + + + + Create Jami account button + + + + + Push button for Jami account creation start trigger + + + + + Create a Jami account + Vytvořit účet Jami + + + + Link device button + + + + + Push button for device linkage start trigger + + + + + Link this device to an account + Připojit toto zařízení k účtu + + + + Create Jami SIP account button + + + + + Push button for Jami SIP account creation start trigger + + + + + Create a SIP account + + + + + Link this device to an existing account + Propojit zařízení s již existujícím účtem + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Ubuntu'; font-size:14px; color:#555555;">To link this device to another account, you first </span><span style=" font-family:'Ubuntu'; font-size:14px; font-weight:600; color:#555555;">need to obtain a PIN</span><span style=" font-family:'Ubuntu'; font-size:14px; color:#555555;"> code. To generate the PIN code:</span></p> +<ol style="margin-top: 0px; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; -qt-list-indent: 1;"><li style=" font-family:'Ubuntu'; font-size:14px; color:#555555;" style=" margin-top:12px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:14px;">Go to the </span><span style=" font-size:14px; font-weight:600;">Account management setting</span><span style=" font-size:14px;"> of a previous device</span></li> +<li style=" font-family:'Ubuntu'; font-size:14px; color:#555555;" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:14px;">Choose the </span><span style=" font-size:14px; font-weight:600;">Jami account</span><span style=" font-size:14px;"> you want to use</span></li> +<li style=" font-family:'Ubuntu'; font-size:14px; color:#555555;" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:14px;">Go to the </span><span style=" font-size:14px; font-weight:600;">Devices</span><span style=" font-size:14px;"> tab</span></li> +<li style=" font-family:'Ubuntu'; font-size:14px; color:#555555;" style=" margin-top:0px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:14px;">Select </span><span style=" font-size:14px; font-weight:600;">Add a device</span></li></ol> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Ubuntu'; font-size:14px; color:#555555;">You will get the necessary PIN to complete this form. The PIN is only valid for </span><span style=" font-family:'Ubuntu'; font-size:14px; font-weight:600; color:#555555;">10 minutes</span><span style=" font-family:'Ubuntu'; font-size:10px; color:#555555;">.</span></p></body></html> + + + + + Enter your pin: + Vložte svůj pin: + + + + Or import a file: + Nebo zavést soubor: + + + + Link from exported account archive file + + + + + + + (None) + (žádný) + + + + Password: + Heslo: + + + + + Profile + Profil + + + + + Profile name + Název profilu + + + + Account + Účet + + + + Register your username. +This will reserve the username so that only you can use it. +Your friends will be able to call you with your usename +instead of using your ID. + + + + + Public username checkbox + Zaškrtávací okénko pro veřejné uživatelské jméno + + + + Checkbox selecting if the user wants a public username + Zaškrtnutí okénka, pokud chce uživatel veřejné uživatelské jméno + + + + Register public username + Zaregistrovat veřejné uživatelské jméno + + + + Public username edit + Upravení veřejného uživatelského jména + + + + Choose your username + Zvolte si uživatelské jméno + + + + Password text input + Zadání textu hesla + + + + Password text entry + Zadání textu hesla + + + + + Password + Heslo + + + + + Password confirmation text input + Textové zadání potvrzení hesla + + + + Confirm password + Potvrdit heslo + + + + SIP Account + Účet SIP + + + + SIP Server edit + + + + + Server + + + + + SIP proxy input + + + + + SIP proxy text entry + + + + + Proxy + Proxy + + + + SIP username input + Zadání uživatelského jména pro SIP + + + + SIP Password text entry + + + + + Username + Uživatelské jméno + + + + + SIP Password text input + + + + + Generating your Jami account… + Vytváří se váš účet Jami… + + + + Previous page button + Předchozí strana + + + + push button to access previous page of wizard + Tlačítko pro vrácení se v průvodci o stranu zpět + + + + Previous + Předchozí + + + + Cancel account create/link + Zrušit vytváření/propojování účtu + + + + push button to cancel account creation or linking + Tlačítko pro zrušení vytváření nebo propojování účtu + + + + Back + Zpět + + + + Next page Button + Další strana + + + + Push button to access next page of wizard + Tlačítko pro přechod na další stranu průvodce + + + + Next + Další + + + + Open File + Otevřít soubor + + + + Jami archive files (*.gz); All files (*) + Archivní soubory Jami (*.gz); Všechny soubory (*) + + + + Your account needs to be migrated. Enter your password. + Váš účet musí být převeden. Zadejte své heslo. + + + + Migrating your Jami account... + Převádí se váš účet Jami… + + + + Importing account archive... + Zavádí se archiv s účtem… + + + + Generating your Jami account... + Vytváří se váš účet Jami… + + + + Generating your SIP account... + + + + + Error creating account + Chyba při vytváření účtu + + + + PasswordDialog + + + Change Account Password + Změnit heslo k účtu + + + + Enter Current Password + Zadejte nynější heslo + + + + Enter New Password + Zadejte nové heslo + + + + Confirm New Password + Potvrďte nové heslo + + + + Confirm + Potvrdit + + + + Cancel + Zrušit + + + + Current Password Incorrect + Nynější heslo je nesprávné + + + + PhotoBoothDialog + + + Photobooth + Fotoautomat + + + + PhotoboothWidget + + + Form + Formulář + + + + Photobooth display + + + + + Choose File + Vybrat soubor + + + + Image Files (*.jpg *.jpeg *.png) + Obrázkové soubory (*.jpg *.jpeg *.png) + + + + PrivateBridging + + + Choose File + Vybrat soubor + + + + Files (*) + Soubory (*) + + + + QObject + + + No default mail client found + Nenalezen žádný výchozí e-mailový klient + + + + + Edit Device Name + Upravit název zařízení + + + + Unlink Device From Account + Odpojit zařízení od účtu + + + + Save new device name + + + + + Add as contact + + + + + RingButton + + + Select folder + Vybrat složku + + + + SettingsWidget + + + Form + Formulář + + + + Settings + Nastavení + + + + Account + Účet + + + + + General + Obecné + + + + + Audio / Video + Zvuk/Obraz + + + + System + Systém + + + + Enable desktop notifications + + + + + Keep minimized on close + Neukončovat Ring po uzavření okna + + + + Download folder + Složka pro stahování + + + + Save in + Uložit do + + + + Always Recording + Vždy nahrávat + + + + Updates + Aktualizace + + + + Check for updates automatically every + + + + + Interval between update checks in days selector + + + + + days + + + + + Check for updates now button + + + + + Check for updates now + Zkontrolovat aktualizace nyní + + + + Password + Heslo + + + + + Enable + Povolit + + + + toggle enable notifications + + + + + Toggle keep minimized on close + + + + + Call Recordings + + + + + Toggle automatic updates + + + + + Jami Account + + + + + + Profile + Profil + + + + + Identity + Totožnost + + + + Id + + + + + Registered name + Registrované jméno + + + + Type here to register a username + + + + + Register + Zaregistrovat + + + + Change Password + Změnit heslo + + + + Export Account + Vyvést účet + + + + + Delete Account + Odstranit účet + + + + Linked Devices + Připojená zařízení + + + + Link Another Device + Připojit další zařízení + + + + Banned Contacts + Zakázané kontakty + + + + Format + + + + + Video device framerate selector + + + + + Preview unavailable + + + + + + Advanced Account Settings + Pokročilá nastavení účtu + + + + SIP Account + Účet SIP + + + + Username + Uživatelské jméno + + + + Hostname + Název serveru + + + + Proxy + Proxy + + + + Audio + Zvuk + + + + Microphone + Mikrofon + + + + Audio input device selector + Výběr vstupního zvukového zařízení + + + + Output Device + Výstupní zařízení + + + + Choose the output device + Vybrat název výstupního zařízení + + + + Video + Video + + + + Device + Zařízení + + + + Video device selector + Výběr obrazového zařízení + + + + A registered name should not have any spaces and must be at least three letters long + + + + + This name is already taken + Toto uživatelské jméno je již zabráno + + + + + Enter an alias + + + + + Register this name + Zaregistrovat toto jméno + + + + Remove Device + Odstranit zařízení + + + + Enter this account's password to confirm the removal of this device + + + + + Are you sure you wish to remove this device? + + + + + Export Account Here + Vyvést účet sem + + + + Select A Folder For Your Downloads + Vyberte složku pro vaše stahování + + + + Select A Folder For Your Recordings + Vyberte složku pro vaše nahrávání + + + + VideoOverlay + + + Call on Hold + Hovor pozastaven + + + + Hold / Unhold + Pozastavit/Pokračovat + + + + Chat + Rozhovor + + + + Mute Mic + Ztlumit mikrofon + + + + Record call + Nahrávat vše + + + + Name label + Název štítku + + + + Time elapsed + Uplynulý čas + + + + 00:00 + 00:00 + + + + Hangup + Zavěsit + + + + Mute Video + Vypnout obraz + + + + VideoView + + + Share entire screen + Sdílet celou obrazovku + + + + Share screen area + Sdílet část obrazovky + + + + Share file + Sdílet soubor + + + \ No newline at end of file diff --git a/translations/ring_client_windows_da.ts b/translations/ring_client_windows_da.ts new file mode 100644 index 00000000..62a01b76 --- /dev/null +++ b/translations/ring_client_windows_da.ts @@ -0,0 +1,1589 @@ + + + AboutDialog + + + + About + Om + + + + about button + om-knap + + + + credits button + krediteringer-knap + + + + Credits + Krediteringer + + + + Free as in Freedom + + + + + The Microsoft Windows client for Jami. +Jami is a secured and distributed communication software. + + + + + version + version + + + + Created by: + Skabt af: + + + + Artwork by: + Grafik af: + + + + Based on the SFLPhone project + Baseret på SFLPhone-projektet + + + + AccountItemDelegate + + + Add Account + + + + + AdvancedSIPSettingsWidget + + + Form + Form + + + + Call Settings + + + + + Auto Answer Calls + + + + + Enable Custom Ringtone + + + + + Connectivity + Forbindelse + + + + STUN Address + + + + + Use STUN + Brug STUN + + + + Use UPnP + + + + + Use TURN + Brug TURN + + + + TURN Password + + + + + TURN Username + + + + + TURN Address + + + + + Media + Medier + + + + Enable Video + Aktiver video + + + + Video Codecs + + + + + Audio Codecs + + + + + Audio Files (*.wav *.ogg *.opus *.mp3 *aiff *wma) + + + + + Add a custom ringtone + + + + + AdvancedSettingsWidget + + + Form + Form + + + + Call Settings + + + + + Allow Calls From Untrusted Peers + + + + + Auto Answer Calls + + + + + Enable Custom Ringtone + + + + + Add a custom ringtone + + + + + Name Server + + + + + Address + Adresse + + + + OpenDHT Configuration + + + + + Enable Proxy + Aktivér proxy + + + + Bootstrap + Bootstrap + + + + Security + Sikkerhed + + + + Private Key Password + Adgangskode for Privatnøgle + + + + User Certificate + Brugercertifikat + + + + Private Key + + + + + CA Certificate + + + + + Connectivity + Forbindelse + + + + Use STUN + Brug STUN + + + + STUN Address + + + + + Use UPnP + + + + + Use TURN + Brug TURN + + + + TURN Password + + + + + TURN Username + + + + + TURN Address + + + + + Media + Medier + + + + Enable Video + Aktiver video + + + + Audio Codecs + + + + + Video Codecs + + + + + Audio Files (*.wav *.ogg *.opus *.mp3 *aiff *wma) + + + + + AnimatedOverlay + + + Form + Form + + + + BannedItemWidget + + + Form + Form + + + + name + + + + + id + + + + + CallWidget + + + Show conversations + + + + + Conversations + Samtaler + + + + Search contact text input + Tekstinput for søg efter kontakt + + + + Jami is free software for universal communication which respects the freedoms and privacy of its users. + Jami is free software for universal communication which respects the freedoms and privacy of its users. (Näcken) + + + + + This is your ID. +Copy and share it with your friends! + + + + + + Show ring ID QR code + + + + + Share ring ID button + Del ring-ID-knap + + + + Double-click to copy + Dobbeltklik for at kopiere + + + + Error while generating QR Code + Fejl ved generering af QR-kode + + + + + best name + + + + + best Id + + + + + Back to homepage button + Tilbage til hjemmeside-knap + + + + Add to contacts + Tilføj til kontakt + + + + Show invites + + + + + Invites + + + + + + Find a new or existing contact + + + + + Wants to talk to you! + Vil tale med dig! + + + + Answer incoming call button + + + + + Ignore incoming call button + Ignorer indgående opkald-knap + + + + Answer + Besvar + + + + Ignore + Afvis + + + + Cancel outgoing call + + + + + Cancel + Annuller + + + + Start video call + Start et video opkald + + + + Start audio call + Start en audio samtale + + + + Clear conversation + Ryd samtale + + + + Remove contact + Fjern kontakt + + + + Block contact + Bloker kontakt + + + + Copy number + Kopiér nummer + + + + Search your received invitations + + + + + Contact me on Jami + + + + + My Id is : + + + + + %1 + %1 is the contact username + %1 + + + + %1 + %1 is the contact unique identifier + %1 + + + + Call incoming from %1 + Indgående kald fra %1 + + + + DeleteAccountDialog + + + Account deletion + + + + + Do you really want to delete the following account? + + + + + If this account hasn't been exported, or added to another device, it will be irrevocably lost. + + + + + Permanently delete account + + + + + Delete + Slet + + + + Cancel account deletion + + + + + Cancel + Annuller + + + + DeviceItemWidget + + + Form + Form + + + + Device Id + + + + + this device + denne enhed + + + + InviteButtonsWidget + + + Accept + Accepter + + + + Refuse + Afvis + + + + Block + Blokér + + + + LinkDeviceDialog + + + Dialog + Dialog + + + + Enter your account password + + + + + Password + Adgangskode + + + + Ok + Ok + + + + Cancel + Annuller + + + + Exporting account + + + + + Your PIN is + + + + + PIN + PIN + + + + This pin and the account password should be entered in your device within 10 minutes. + + + + + Close + Luk + + + + Link Another Device + + + + + Incorrect password + Forkert adgangskode + + + + Something went wrong. +Please try again later. + + + + + MainWindow + + + Settings + Indstillinger + + + + Exit + Afslut + + + + About + Om + + + + Jami + Jami + + + + NameRegistrationDialog + + + Set Registered Name + + + + + Enter your account password + + + + + Password text input + Tekstinput for adgangskode + + + + Password text entry + Tekstindtastning for adgangskode + + + + Password + Adgangskode + + + + Register + Registrér + + + + Cancel + Annuller + + + + Registering Name + + + + + Something went wrong + + + + + Close + Luk + + + + Incorrect password + Forkert adgangskode + + + + Network error + Netværksfejl + + + + NewWizardWidget + + + Form + Form + + + + Welcome Label + + + + + Welcome to + Velkommen til + + + + Welcome Logo + + + + + Create Jami account button + + + + + Push button for Jami account creation start trigger + + + + + Create a Jami account + + + + + Link device button + Tilknyt enhed-knap + + + + Push button for device linkage start trigger + + + + + Link this device to an account + Tilknyt denne enhed til en konto + + + + Create Jami SIP account button + + + + + Push button for Jami SIP account creation start trigger + + + + + Create a SIP account + + + + + Link this device to an existing account + Tilnyt denne enhed til en eksisterende konto + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Ubuntu'; font-size:14px; color:#555555;">To link this device to another account, you first </span><span style=" font-family:'Ubuntu'; font-size:14px; font-weight:600; color:#555555;">need to obtain a PIN</span><span style=" font-family:'Ubuntu'; font-size:14px; color:#555555;"> code. To generate the PIN code:</span></p> +<ol style="margin-top: 0px; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; -qt-list-indent: 1;"><li style=" font-family:'Ubuntu'; font-size:14px; color:#555555;" style=" margin-top:12px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:14px;">Go to the </span><span style=" font-size:14px; font-weight:600;">Account management setting</span><span style=" font-size:14px;"> of a previous device</span></li> +<li style=" font-family:'Ubuntu'; font-size:14px; color:#555555;" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:14px;">Choose the </span><span style=" font-size:14px; font-weight:600;">Jami account</span><span style=" font-size:14px;"> you want to use</span></li> +<li style=" font-family:'Ubuntu'; font-size:14px; color:#555555;" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:14px;">Go to the </span><span style=" font-size:14px; font-weight:600;">Devices</span><span style=" font-size:14px;"> tab</span></li> +<li style=" font-family:'Ubuntu'; font-size:14px; color:#555555;" style=" margin-top:0px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:14px;">Select </span><span style=" font-size:14px; font-weight:600;">Add a device</span></li></ol> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Ubuntu'; font-size:14px; color:#555555;">You will get the necessary PIN to complete this form. The PIN is only valid for </span><span style=" font-family:'Ubuntu'; font-size:14px; font-weight:600; color:#555555;">10 minutes</span><span style=" font-family:'Ubuntu'; font-size:10px; color:#555555;">.</span></p></body></html> + + + + + Enter your pin: + Indtast PIN-kode: + + + + Or import a file: + Eller importér en fil: + + + + Link from exported account archive file + Tilknyt fra eksporteret konto-arkivfil + + + + + + (None) + + + + + Password: + Adgangskode: + + + + + Profile + Profil + + + + + Profile name + + + + + Account + Konto + + + + Register your username. +This will reserve the username so that only you can use it. +Your friends will be able to call you with your usename +instead of using your ID. + + + + + Public username checkbox + + + + + Checkbox selecting if the user wants a public username + + + + + Register public username + Registrer offentligt brugernavn + + + + Public username edit + + + + + Choose your username + Vælg dit brugernavn + + + + Password text input + Tekstinput for adgangskode + + + + Password text entry + Tekstindtastning for adgangskode + + + + + Password + Adgangskode + + + + + Password confirmation text input + Tekstinput for bekræftelse af adgangskode + + + + Confirm password + Bekræft adgangskode + + + + SIP Account + SIP-konto + + + + SIP Server edit + + + + + Server + + + + + SIP proxy input + + + + + SIP proxy text entry + + + + + Proxy + Stedfortræder + + + + SIP username input + Input af SIP-brugernavn + + + + SIP Password text entry + + + + + Username + Brugernavn + + + + + SIP Password text input + + + + + Generating your Jami account… + + + + + Previous page button + Forrige side-knap + + + + push button to access previous page of wizard + + + + + Previous + Tilbage + + + + Cancel account create/link + + + + + push button to cancel account creation or linking + + + + + Back + Tilbage + + + + Next page Button + Næste side-knap + + + + Push button to access next page of wizard + + + + + Next + Næste + + + + Open File + Åbn fil + + + + Jami archive files (*.gz); All files (*) + + + + + Your account needs to be migrated. Enter your password. + Din konto kræver migrering. Indtast din adgangskode. + + + + Migrating your Jami account... + + + + + Importing account archive... + + + + + Generating your Jami account... + + + + + Generating your SIP account... + + + + + Error creating account + + + + + PasswordDialog + + + Change Account Password + + + + + Enter Current Password + + + + + Enter New Password + + + + + Confirm New Password + + + + + Confirm + + + + + Cancel + Annuller + + + + Current Password Incorrect + + + + + PhotoBoothDialog + + + Photobooth + Fotobås + + + + PhotoboothWidget + + + Form + Form + + + + Photobooth display + + + + + Choose File + Vælg fil + + + + Image Files (*.jpg *.jpeg *.png) + + + + + PrivateBridging + + + Choose File + Vælg fil + + + + Files (*) + Filer (*) + + + + QObject + + + No default mail client found + Ingen standard mail-klient fundet + + + + + Edit Device Name + + + + + Unlink Device From Account + + + + + Save new device name + + + + + Add as contact + + + + + RingButton + + + Select folder + Vælg mappe + + + + SettingsWidget + + + Form + Form + + + + Settings + Indstillinger + + + + Account + Konto + + + + + General + Generelt + + + + + Audio / Video + + + + + System + System + + + + Enable desktop notifications + + + + + Keep minimized on close + Hold minimeret ved lukning + + + + Download folder + + + + + Save in + Gem i + + + + Always Recording + + + + + Updates + + + + + Check for updates automatically every + + + + + Interval between update checks in days selector + + + + + days + + + + + Check for updates now button + + + + + Check for updates now + Søg efter for opdateringer nu + + + + Password + Adgangskode + + + + + Enable + Tillad + + + + toggle enable notifications + + + + + Toggle keep minimized on close + + + + + Call Recordings + + + + + Toggle automatic updates + + + + + Jami Account + + + + + + Profile + Profil + + + + + Identity + Identitet + + + + Id + + + + + Registered name + Registreret navn + + + + Type here to register a username + + + + + Register + Registrér + + + + Change Password + + + + + Export Account + Eksport konto + + + + + Delete Account + + + + + Linked Devices + + + + + Link Another Device + + + + + Banned Contacts + Blokerede kontakter + + + + Format + + + + + Video device framerate selector + + + + + Preview unavailable + + + + + + Advanced Account Settings + + + + + SIP Account + SIP-konto + + + + Username + Brugernavn + + + + Hostname + Værtsnavn + + + + Proxy + Stedfortræder + + + + Audio + Lyd + + + + Microphone + + + + + Audio input device selector + + + + + Output Device + Outputenhed + + + + Choose the output device + + + + + Video + Video + + + + Device + Enhed + + + + Video device selector + + + + + A registered name should not have any spaces and must be at least three letters long + + + + + This name is already taken + + + + + + Enter an alias + + + + + Register this name + + + + + Remove Device + + + + + Enter this account's password to confirm the removal of this device + + + + + Are you sure you wish to remove this device? + + + + + Export Account Here + + + + + Select A Folder For Your Downloads + + + + + Select A Folder For Your Recordings + + + + + VideoOverlay + + + Call on Hold + Samtale parkeret + + + + Hold / Unhold + Parkeret / Aktiv + + + + Chat + Chat + + + + Mute Mic + Sluk mikrofon + + + + Record call + Optag opkald + + + + Name label + Navne etiket + + + + Time elapsed + Tid gået + + + + 00:00 + 00:00 + + + + Hangup + Læg på + + + + Mute Video + Sluk mikrofon + + + + VideoView + + + Share entire screen + Del hele skærmen + + + + Share screen area + Del skærmområde + + + + Share file + Del fil + + + \ No newline at end of file diff --git a/translations/ring_client_windows_da_DK.ts b/translations/ring_client_windows_da_DK.ts new file mode 100644 index 00000000..b13f0bb4 --- /dev/null +++ b/translations/ring_client_windows_da_DK.ts @@ -0,0 +1,1591 @@ + + + + + AboutDialog + + + + About + Om + + + + about button + Knap til om + + + + credits button + Knap til krediteringer + + + + Credits + Krediteringer + + + + Free as in Freedom + + + + + The Microsoft Windows client for Jami. +Jami is a secured and distributed communication software. + + + + + version + version + + + + Created by: + Skabt af: + + + + Artwork by: + Grafik af: + + + + Based on the SFLPhone project + Baseret på SFLPhone-projektet + + + + AccountItemDelegate + + + Add Account + + + + + AdvancedSIPSettingsWidget + + + Form + Form + + + + Call Settings + + + + + Auto Answer Calls + + + + + Enable Custom Ringtone + + + + + Connectivity + + + + + STUN Address + + + + + Use STUN + Brug STUN + + + + Use UPnP + + + + + Use TURN + Brug TURN + + + + TURN Password + + + + + TURN Username + + + + + TURN Address + + + + + Media + + + + + Enable Video + + + + + Video Codecs + + + + + Audio Codecs + + + + + Audio Files (*.wav *.ogg *.opus *.mp3 *aiff *wma) + + + + + Add a custom ringtone + + + + + AdvancedSettingsWidget + + + Form + Form + + + + Call Settings + + + + + Allow Calls From Untrusted Peers + + + + + Auto Answer Calls + + + + + Enable Custom Ringtone + + + + + Add a custom ringtone + + + + + Name Server + + + + + Address + Adresse + + + + OpenDHT Configuration + + + + + Enable Proxy + + + + + Bootstrap + + + + + Security + Sikkerhed + + + + Private Key Password + + + + + User Certificate + + + + + Private Key + + + + + CA Certificate + + + + + Connectivity + + + + + Use STUN + Brug STUN + + + + STUN Address + + + + + Use UPnP + + + + + Use TURN + Brug TURN + + + + TURN Password + + + + + TURN Username + + + + + TURN Address + + + + + Media + + + + + Enable Video + + + + + Audio Codecs + + + + + Video Codecs + + + + + Audio Files (*.wav *.ogg *.opus *.mp3 *aiff *wma) + + + + + AnimatedOverlay + + + Form + Form + + + + BannedItemWidget + + + Form + Form + + + + name + + + + + id + + + + + CallWidget + + + Show conversations + + + + + Conversations + Samtaler + + + + Search contact text input + + + + + Jami is free software for universal communication which respects the freedoms and privacy of its users. + + + + + + This is your ID. +Copy and share it with your friends! + + + + + + Show ring ID QR code + + + + + Share ring ID button + + + + + Double-click to copy + Dobbeltklik for at kopiere + + + + Error while generating QR Code + Fejl ved generering af QR code + + + + + best name + + + + + best Id + + + + + Back to homepage button + + + + + Add to contacts + Tilføj til kontakt + + + + Show invites + + + + + Invites + + + + + + Find a new or existing contact + + + + + Wants to talk to you! + Vil tale med dig! + + + + Answer incoming call button + + + + + Ignore incoming call button + + + + + Answer + Besvar + + + + Ignore + Afvis + + + + Cancel outgoing call + + + + + Cancel + Annuller + + + + Start video call + + + + + Start audio call + + + + + Clear conversation + + + + + Remove contact + + + + + Block contact + + + + + Copy number + Kopiér nummer + + + + Search your received invitations + + + + + Contact me on Jami + + + + + My Id is : + + + + + %1 + %1 is the contact username + %1 + + + + %1 + %1 is the contact unique identifier + %1 + + + + Call incoming from %1 + Indgående kald fra %1 + + + + DeleteAccountDialog + + + Account deletion + + + + + Do you really want to delete the following account? + + + + + If this account hasn't been exported, or added to another device, it will be irrevocably lost. + + + + + Permanently delete account + + + + + Delete + + + + + Cancel account deletion + + + + + Cancel + Annuller + + + + DeviceItemWidget + + + Form + Form + + + + Device Id + + + + + this device + + + + + InviteButtonsWidget + + + Accept + + + + + Refuse + + + + + Block + + + + + LinkDeviceDialog + + + Dialog + + + + + Enter your account password + + + + + Password + Adgangskode + + + + Ok + Ok + + + + Cancel + Annuller + + + + Exporting account + + + + + Your PIN is + + + + + PIN + PIN + + + + This pin and the account password should be entered in your device within 10 minutes. + + + + + Close + + + + + Link Another Device + + + + + Incorrect password + + + + + Something went wrong. +Please try again later. + + + + + MainWindow + + + Settings + Indstillinger + + + + Exit + Afslut + + + + About + Om + + + + Jami + + + + + NameRegistrationDialog + + + Set Registered Name + + + + + Enter your account password + + + + + Password text input + + + + + Password text entry + + + + + Password + Adgangskode + + + + Register + + + + + Cancel + Annuller + + + + Registering Name + + + + + Something went wrong + + + + + Close + + + + + Incorrect password + + + + + Network error + + + + + NewWizardWidget + + + Form + Form + + + + Welcome Label + + + + + Welcome to + Velkommen til + + + + Welcome Logo + + + + + Create Jami account button + + + + + Push button for Jami account creation start trigger + + + + + Create a Jami account + + + + + Link device button + + + + + Push button for device linkage start trigger + + + + + Link this device to an account + Tilknyt denne enhed til en konto + + + + Create Jami SIP account button + + + + + Push button for Jami SIP account creation start trigger + + + + + Create a SIP account + + + + + Link this device to an existing account + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Ubuntu'; font-size:14px; color:#555555;">To link this device to another account, you first </span><span style=" font-family:'Ubuntu'; font-size:14px; font-weight:600; color:#555555;">need to obtain a PIN</span><span style=" font-family:'Ubuntu'; font-size:14px; color:#555555;"> code. To generate the PIN code:</span></p> +<ol style="margin-top: 0px; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; -qt-list-indent: 1;"><li style=" font-family:'Ubuntu'; font-size:14px; color:#555555;" style=" margin-top:12px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:14px;">Go to the </span><span style=" font-size:14px; font-weight:600;">Account management setting</span><span style=" font-size:14px;"> of a previous device</span></li> +<li style=" font-family:'Ubuntu'; font-size:14px; color:#555555;" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:14px;">Choose the </span><span style=" font-size:14px; font-weight:600;">Jami account</span><span style=" font-size:14px;"> you want to use</span></li> +<li style=" font-family:'Ubuntu'; font-size:14px; color:#555555;" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:14px;">Go to the </span><span style=" font-size:14px; font-weight:600;">Devices</span><span style=" font-size:14px;"> tab</span></li> +<li style=" font-family:'Ubuntu'; font-size:14px; color:#555555;" style=" margin-top:0px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:14px;">Select </span><span style=" font-size:14px; font-weight:600;">Add a device</span></li></ol> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Ubuntu'; font-size:14px; color:#555555;">You will get the necessary PIN to complete this form. The PIN is only valid for </span><span style=" font-family:'Ubuntu'; font-size:14px; font-weight:600; color:#555555;">10 minutes</span><span style=" font-family:'Ubuntu'; font-size:10px; color:#555555;">.</span></p></body></html> + + + + + Enter your pin: + + + + + Or import a file: + + + + + Link from exported account archive file + + + + + + + (None) + + + + + Password: + + + + + + Profile + + + + + + Profile name + + + + + Account + Konto + + + + Register your username. +This will reserve the username so that only you can use it. +Your friends will be able to call you with your usename +instead of using your ID. + + + + + Public username checkbox + + + + + Checkbox selecting if the user wants a public username + + + + + Register public username + + + + + Public username edit + + + + + Choose your username + Vælg dit brugernavn + + + + Password text input + + + + + Password text entry + + + + + + Password + Adgangskode + + + + + Password confirmation text input + + + + + Confirm password + Bekræft adgangskode + + + + SIP Account + + + + + SIP Server edit + + + + + Server + + + + + SIP proxy input + + + + + SIP proxy text entry + + + + + Proxy + Stedfortræder + + + + SIP username input + + + + + SIP Password text entry + + + + + Username + Brugernavn + + + + + SIP Password text input + + + + + Generating your Jami account… + + + + + Previous page button + + + + + push button to access previous page of wizard + + + + + Previous + Tilbage + + + + Cancel account create/link + + + + + push button to cancel account creation or linking + + + + + Back + + + + + Next page Button + + + + + Push button to access next page of wizard + + + + + Next + Næste + + + + Open File + Åbn fil + + + + Jami archive files (*.gz); All files (*) + + + + + Your account needs to be migrated. Enter your password. + Din konto kræver migrering. Indtast din adgangskode. + + + + Migrating your Jami account... + + + + + Importing account archive... + + + + + Generating your Jami account... + + + + + Generating your SIP account... + + + + + Error creating account + + + + + PasswordDialog + + + Change Account Password + + + + + Enter Current Password + + + + + Enter New Password + + + + + Confirm New Password + + + + + Confirm + + + + + Cancel + Annuller + + + + Current Password Incorrect + + + + + PhotoBoothDialog + + + Photobooth + Fotobås + + + + PhotoboothWidget + + + Form + Form + + + + Photobooth display + + + + + Choose File + Vælg fil + + + + Image Files (*.jpg *.jpeg *.png) + + + + + PrivateBridging + + + Choose File + Vælg fil + + + + Files (*) + Filer (*) + + + + QObject + + + No default mail client found + Ingen standard mail-klient fundet + + + + + Edit Device Name + + + + + Unlink Device From Account + + + + + Save new device name + + + + + Add as contact + + + + + RingButton + + + Select folder + + + + + SettingsWidget + + + Form + Form + + + + Settings + Indstillinger + + + + Account + Konto + + + + + General + Generelt + + + + + Audio / Video + + + + + System + + + + + Enable desktop notifications + + + + + Keep minimized on close + + + + + Download folder + + + + + Save in + + + + + Always Recording + + + + + Updates + + + + + Check for updates automatically every + + + + + Interval between update checks in days selector + + + + + days + + + + + Check for updates now button + + + + + Check for updates now + + + + + Password + Adgangskode + + + + + Enable + + + + + toggle enable notifications + + + + + Toggle keep minimized on close + + + + + Call Recordings + + + + + Toggle automatic updates + + + + + Jami Account + + + + + + Profile + + + + + + Identity + + + + + Id + + + + + Registered name + + + + + Type here to register a username + + + + + Register + + + + + Change Password + + + + + Export Account + + + + + + Delete Account + + + + + Linked Devices + + + + + Link Another Device + + + + + Banned Contacts + Blokerede kontakter + + + + Format + + + + + Video device framerate selector + + + + + Preview unavailable + + + + + + Advanced Account Settings + + + + + SIP Account + + + + + Username + Brugernavn + + + + Hostname + Værtsnavn + + + + Proxy + Stedfortræder + + + + Audio + + + + + Microphone + + + + + Audio input device selector + + + + + Output Device + + + + + Choose the output device + + + + + Video + + + + + Device + + + + + Video device selector + + + + + A registered name should not have any spaces and must be at least three letters long + + + + + This name is already taken + + + + + + Enter an alias + + + + + Register this name + + + + + Remove Device + + + + + Enter this account's password to confirm the removal of this device + + + + + Are you sure you wish to remove this device? + + + + + Export Account Here + + + + + Select A Folder For Your Downloads + + + + + Select A Folder For Your Recordings + + + + + VideoOverlay + + + Call on Hold + Samtale parkeret + + + + Hold / Unhold + Parkeret / Aktiv + + + + Chat + Chat + + + + Mute Mic + Sluk mikrofon + + + + Record call + + + + + Name label + Navne etiket + + + + Time elapsed + Tid gået + + + + 00:00 + 00:00 + + + + Hangup + Læg på + + + + Mute Video + Sluk mikrofon + + + + VideoView + + + Share entire screen + Del hele skærmen + + + + Share screen area + Del skærmområde + + + + Share file + Del fil + + + diff --git a/translations/ring_client_windows_de.ts b/translations/ring_client_windows_de.ts new file mode 100644 index 00000000..7398fa55 --- /dev/null +++ b/translations/ring_client_windows_de.ts @@ -0,0 +1,1606 @@ + + + AboutDialog + + + + About + Über + + + + about button + Über Button + + + + credits button + Credits Button + + + + Credits + Würdigung + + + + Free as in Freedom + Frei wie in Freiheit + + + + The Microsoft Windows client for Jami. +Jami is a secured and distributed communication software. + Die Microsoft Windows Anwendung für Jami. +Jami ist eine sichere und verteilte Kommunikationsanwendung. + + + + version + Version + + + + Created by: + Erstellt von: + + + + Artwork by: + Visuelle Gestaltung: + + + + Based on the SFLPhone project + Basierend auf dem SFLPhone-Projekt + + + + AccountItemDelegate + + + Add Account + Konto hinzufügen + + + + AdvancedSIPSettingsWidget + + + Form + Formular + + + + Call Settings + Anrufeinstellungen + + + + Auto Answer Calls + Anrufe automatisch beantworten + + + + Enable Custom Ringtone + Eigenen Klingelton aktivieren + + + + Connectivity + Verbindung + + + + STUN Address + STUN Adresse + + + + Use STUN + STUN benutzen + + + + Use UPnP + UPnP benutzen + + + + Use TURN + TURN benutzen + + + + TURN Password + TURN Passwort + + + + TURN Username + TURN Benutzername + + + + TURN Address + TURN Adresse + + + + Media + Medium + + + + Enable Video + Video aktivieren + + + + Video Codecs + Video Codecs + + + + Audio Codecs + Audio Codecs + + + + Audio Files (*.wav *.ogg *.opus *.mp3 *aiff *wma) + Audiodateien (*.wav *.ogg *.opus *.mp3 *aiff *wma) + + + + Add a custom ringtone + Eigenen Klingelton hinzufügen + + + + AdvancedSettingsWidget + + + Form + Formular + + + + Call Settings + Anrufeinstellungen + + + + Allow Calls From Untrusted Peers + Erlaube Anruf von unbekannten Teilnehmern + + + + Auto Answer Calls + Anrufe automatisch beantworten + + + + Enable Custom Ringtone + Eigenen Klingelton aktivieren + + + + Add a custom ringtone + Eigenen Klingelton hinzufügen + + + + Name Server + Server für Benutzernamen + + + + Address + Adresse + + + + OpenDHT Configuration + OpenDHT-Einstellungen + + + + Enable Proxy + Proxy aktivieren + + + + Bootstrap + Aktivierung + + + + Security + Sicherheit + + + + Private Key Password + Passwort für den privaten Schlüssel + + + + User Certificate + Benutzerzertifikat + + + + Private Key + Privater Schlüssel + + + + CA Certificate + CA-Zertifikat + + + + Connectivity + Verbindungsmöglichkeiten + + + + Use STUN + STUN benutzen + + + + STUN Address + STUN Adresse + + + + Use UPnP + UPnP benutzen + + + + Use TURN + TURN benutzen + + + + TURN Password + TURN Passwort + + + + TURN Username + TURN Benutzername + + + + TURN Address + TURN Adresse + + + + Media + Medium + + + + Enable Video + Video aktivieren + + + + Audio Codecs + Audio Codecs + + + + Video Codecs + Video Codecs + + + + Audio Files (*.wav *.ogg *.opus *.mp3 *aiff *wma) + Audiodateien (*.wav *.ogg *.opus *.mp3 *aiff *wma) + + + + AnimatedOverlay + + + Form + Formular + + + + BannedItemWidget + + + Form + Formular + + + + name + Name + + + + id + Jami-ID + + + + CallWidget + + + Show conversations + Zeige Unterhaltungen + + + + Conversations + Unterhaltungen + + + + Search contact text input + Nach Kontakte suchen Eingabe + + + + Jami is free software for universal communication which respects the freedoms and privacy of its users. + Jami ist eine freie Software für universelle Kommunikation und respektiert die Freiheiten und Privatsphäre der Benutzer. + + + + + This is your ID. +Copy and share it with your friends! + + + Das ist Ihre Jami-ID. +Kopieren und teilen Sie diese mit Ihren Freunden! + + + + + Show ring ID QR code + Zeige Ring-ID QR-Code + + + + Share ring ID button + Teile Ring-ID Button + + + + Double-click to copy + Doppelklick zum kopieren + + + + Error while generating QR Code + Fehler bei der Erstellung des QR-Codes + + + + + best name + Bester Name + + + + best Id + Bester ID + + + + Back to homepage button + Zurück zur Übersicht Button + + + + Add to contacts + Zu Kontakten hinzufügen + + + + Show invites + Zeige Einladungen + + + + Invites + Einladungen + + + + + Find a new or existing contact + Suche nach neuen oder existierenden Kontakten + + + + Wants to talk to you! + Möchte mit dir Sprechen + + + + Answer incoming call button + Eingehenden Anruf annehmen Button + + + + Ignore incoming call button + Eingehenden Anruf ignorieren Button + + + + Answer + Antwort + + + + Ignore + Ignorieren + + + + Cancel outgoing call + Ausgehenden Anruf abbrechen + + + + Cancel + Abbrechen + + + + Start video call + Videoanruf starten + + + + Start audio call + Audioanruf starten + + + + Clear conversation + Gesprächsverlauf löschen + + + + Remove contact + Entferne Kontakt + + + + Block contact + Kontakt blockieren + + + + Copy number + Nummer kopieren + + + + Search your received invitations + Suche in empfangenen Einladungen + + + + Contact me on Jami + Kontaktieren Sie mich über Jami + + + + My Id is : + Meine ID ist: + + + + %1 + %1 is the contact username + %1 + + + + %1 + %1 is the contact unique identifier + %1 + + + + Call incoming from %1 + Eingehender Anruf von %1 + + + + DeleteAccountDialog + + + Account deletion + Kontolöschung + + + + Do you really want to delete the following account? + Möchten Sie wirklich das folgende Konto löschen? + + + + If this account hasn't been exported, or added to another device, it will be irrevocably lost. + Falls dieses Konto nicht exportiert oder auf ein anderes Gerät übertragen wurde, wird es endgültig verloren gehen. + + + + Permanently delete account + Konto permanent löschen + + + + Delete + Löschen + + + + Cancel account deletion + Kontolöschung abbrechen + + + + Cancel + Abbrechen + + + + DeviceItemWidget + + + Form + Formular + + + + Device Id + Gerätekennung + + + + this device + dieses Gerät + + + + InviteButtonsWidget + + + Accept + Akzeptieren + + + + Refuse + Verweigern + + + + Block + Sperren + + + + LinkDeviceDialog + + + Dialog + Dialog + + + + Enter your account password + Geben Sie ihr Kontopasswort ein + + + + Password + Passwort + + + + Ok + Ok + + + + Cancel + Abbrechen + + + + Exporting account + Konto wird exportiert + + + + Your PIN is + Ihre PIN ist + + + + PIN + PIN + + + + This pin and the account password should be entered in your device within 10 minutes. + Diese PIN und das Kontopasswort sollten bei ihrem Gerät innerhalb von 10 Minuten eingegeben werden. + + + + Close + Schließen + + + + Link Another Device + Weiteres Gerät verknüpfen + + + + Incorrect password + Falsches Passwort + + + + Something went wrong. +Please try again later. + Irgendetwas ist schief gelaufen. +Bitte versuchen sie es später nocheinmal. + + + + MainWindow + + + Settings + Einstellungen + + + + Exit + Schliessen + + + + About + Über + + + + Jami + Jami + + + + NameRegistrationDialog + + + Set Registered Name + Registrierten Namen setzen + + + + Enter your account password + Geben Sie ihr Kontopasswort ein + + + + Password text input + Passwort-Eingabe + + + + Password text entry + Passwort-Eintrag + + + + Password + Passwort + + + + Register + Registrieren + + + + Cancel + Abbrechen + + + + Registering Name + Name für Registrierung + + + + Something went wrong + Irgendetwas ist schief gelaufen + + + + Close + Schließen + + + + Incorrect password + Falsches Passwort + + + + Network error + Netzwerkfehler + + + + NewWizardWidget + + + Form + Formular + + + + Welcome Label + Begrüßungslabel + + + + Welcome to + Willkommen bei + + + + Welcome Logo + Begrüßungslogo + + + + Create Jami account button + Jami-Konto anlegen Button + + + + Push button for Jami account creation start trigger + Auf Button klicken um Jami-Konto zu erstellen + + + + Create a Jami account + Ein Jami-Konto erstellen + + + + Link device button + Verbinde Gerät Button + + + + Push button for device linkage start trigger + Auf Button klicken um ein Gerät zu verbinden + + + + Link this device to an account + Dieses Gerät mit einem Konto verknüpfen + + + + Create Jami SIP account button + Jami-SIP-Konto erstellen Button + + + + Push button for Jami SIP account creation start trigger + Auf Button klicken um Jami-SIP-Konto zu erstellen + + + + Create a SIP account + SIP-Konto erstellen + + + + Link this device to an existing account + Dieses Gerät mit einem vorhandenen Konto verknüpfen + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Ubuntu'; font-size:14px; color:#555555;">To link this device to another account, you first </span><span style=" font-family:'Ubuntu'; font-size:14px; font-weight:600; color:#555555;">need to obtain a PIN</span><span style=" font-family:'Ubuntu'; font-size:14px; color:#555555;"> code. To generate the PIN code:</span></p> +<ol style="margin-top: 0px; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; -qt-list-indent: 1;"><li style=" font-family:'Ubuntu'; font-size:14px; color:#555555;" style=" margin-top:12px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:14px;">Go to the </span><span style=" font-size:14px; font-weight:600;">Account management setting</span><span style=" font-size:14px;"> of a previous device</span></li> +<li style=" font-family:'Ubuntu'; font-size:14px; color:#555555;" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:14px;">Choose the </span><span style=" font-size:14px; font-weight:600;">Jami account</span><span style=" font-size:14px;"> you want to use</span></li> +<li style=" font-family:'Ubuntu'; font-size:14px; color:#555555;" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:14px;">Go to the </span><span style=" font-size:14px; font-weight:600;">Devices</span><span style=" font-size:14px;"> tab</span></li> +<li style=" font-family:'Ubuntu'; font-size:14px; color:#555555;" style=" margin-top:0px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:14px;">Select </span><span style=" font-size:14px; font-weight:600;">Add a device</span></li></ol> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Ubuntu'; font-size:14px; color:#555555;">You will get the necessary PIN to complete this form. The PIN is only valid for </span><span style=" font-family:'Ubuntu'; font-size:14px; font-weight:600; color:#555555;">10 minutes</span><span style=" font-family:'Ubuntu'; font-size:10px; color:#555555;">.</span></p></body></html> + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Ubuntu'; font-size:14px; color:#555555;">Um dieses Gerät mit einem anderen Konto zu verbinden </span><span style=" font-family:'Ubuntu'; font-size:14px; font-weight:600; color:#555555;">benötigt man einen PIN Code. </span><span style=" font-family:'Ubuntu'; font-size:14px; color:#555555;">Um den PIN Code zu generieren muss man folgendes machen: </span></p> +<ol style="margin-top: 0px; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; -qt-list-indent: 1;"><li style=" font-family:'Ubuntu'; font-size:14px; color:#555555;" style=" margin-top:12px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:14px;">Gehe in die </span><span style=" font-size:14px; font-weight:600;">Kontoeinstellungen</span><span style=" font-size:14px;"> eines anderen bereits verbundenen Gerätes</span></li> +<li style=" font-family:'Ubuntu'; font-size:14px; color:#555555;" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:14px;">Wähle das </span><span style=" font-size:14px; font-weight:600;">Jami-Konto</span><span style=" font-size:14px;">, dass du verwenden möchtest</span></li> +<li style=" font-family:'Ubuntu'; font-size:14px; color:#555555;" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:14px;">Gehe in den </span><span style=" font-size:14px; font-weight:600;">Geräte</span><span style=" font-size:14px;"> Reiter</span></li> +<li style=" font-family:'Ubuntu'; font-size:14px; color:#555555;" style=" margin-top:0px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:14px;">Wähle </span><span style=" font-size:14px; font-weight:600;">Gerät hinzufügen</span><span style=" font-size:14px;"> aus</span></li></ol> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Ubuntu'; font-size:14px; color:#555555;">Dort bekommen Sie den notwendigen PIN Code. Die PIN ist nur gültig für </span><span style=" font-family:'Ubuntu'; font-size:14px; font-weight:600; color:#555555;">10 Minuten</span><span style=" font-family:'Ubuntu'; font-size:10px; color:#555555;">.</span></p></body></html> + + + + Enter your pin: + Geben Sie Ihre PIN ein: + + + + Or import a file: + Oder eine Datei importieren: + + + + Link from exported account archive file + Gerät über exportierte Archivdatei verbinden + + + + + + (None) + (Nichts) + + + + Password: + Passwort: + + + + + Profile + Profil + + + + + Profile name + Profilname + + + + Account + Konto + + + + Register your username. +This will reserve the username so that only you can use it. +Your friends will be able to call you with your usename +instead of using your ID. + Registriere deinen Benutzernamen. +Dadurch wird er für dich reserviert, sodass nur du ihn benutzen kannst. +Deine Freunde werden dich dann über deinen Benutzernamen +anstatt deiner Jami-ID anrufen können. + + + + Public username checkbox + Öffentliches Benutzernamen Kästchen + + + + Checkbox selecting if the user wants a public username + Kästchen, das festlegt ob der Benutzer einen öffentlichen Benutzernamen will + + + + Register public username + Öffentlichen Benutzernamen registrieren + + + + Public username edit + Öffentlicher Benutzername Änderung + + + + Choose your username + Nutzername wählen + + + + Password text input + Passwort-Eingabe + + + + Password text entry + Passwort-Eintrag + + + + + Password + Passwort + + + + + Password confirmation text input + Passwortbestätigungs-Eingabe + + + + Confirm password + Passwort bestätigen + + + + SIP Account + SIP-Konto + + + + SIP Server edit + SIP-Server Änderung + + + + Server + Server + + + + SIP proxy input + SIP-Proxy-Eingabe + + + + SIP proxy text entry + SIP-Proxy-Eintrag + + + + Proxy + Proxy + + + + SIP username input + SIP-Benutzername-Eingabe + + + + SIP Password text entry + SIP-Passwort-Eintrag + + + + Username + Benutzername + + + + + SIP Password text input + SIP-Passwort-Eingabe + + + + Generating your Jami account… + Erzeugen Ihres Jami-Kontos... + + + + Previous page button + Vorherige Seite Button + + + + push button to access previous page of wizard + Button um auf die vorherige Seite des Konfigurationsassistenten zu kommen + + + + Previous + Vorherige + + + + Cancel account create/link + Kontoerstellung/-verbindung abbrechen + + + + push button to cancel account creation or linking + Button um Kontoerstellung oder Kontoverbindung abzubrechen + + + + Back + Zurück + + + + Next page Button + Nächste Seite Button + + + + Push button to access next page of wizard + Button um auf die nächste Seite des Konfigurationsassistenten zu kommen + + + + Next + Weiter + + + + Open File + Datei öffnen + + + + Jami archive files (*.gz); All files (*) + Jami Archivdatei (*.gz); Alle Dateien (*) + + + + Your account needs to be migrated. Enter your password. + Ihr Konto muss migriert werden. Bitte geben Sie Ihr Passwort ein. + + + + Migrating your Jami account... + Ihr Jami-Konto wird migriert... + + + + Importing account archive... + Kontoarchiv wird importiert... + + + + Generating your Jami account... + Ihr Jami Konto wird erzeugt... + + + + Generating your SIP account... + Ihr SIP-Konto wird erzeugt... + + + + Error creating account + Fehler beim Erstellen des Kontos + + + + PasswordDialog + + + Change Account Password + Kontopasswort ändern + + + + Enter Current Password + Aktuelles Passwort eingeben + + + + Enter New Password + Neues Passwort eingeben + + + + Confirm New Password + Neues Passwort bestätigen + + + + Confirm + Bestätigen + + + + Cancel + Abbrechen + + + + Current Password Incorrect + Aktuelles Passwort falsch + + + + PhotoBoothDialog + + + Photobooth + Photobooth + + + + PhotoboothWidget + + + Form + Formular + + + + Photobooth display + Fotoautomatenanzeige + + + + Choose File + Datei auswählen + + + + Image Files (*.jpg *.jpeg *.png) + Bilddateien (*.jpg *.jpeg *.png) + + + + PrivateBridging + + + Choose File + Datei auswählen + + + + Files (*) + Dateien (*) + + + + QObject + + + No default mail client found + Kein Standardprogramm für E‑Mail gefunden + + + + + Edit Device Name + Gerätename ändern + + + + Unlink Device From Account + Kontoverknüpfung von Gerät auflösen + + + + Save new device name + Neuen Gerätenamen speichern + + + + Add as contact + Als Kontakt hinzufügen + + + + RingButton + + + Select folder + Ordner auswählen + + + + SettingsWidget + + + Form + Formular + + + + Settings + Einstellungen + + + + Account + Konto + + + + + General + Allgemein + + + + + Audio / Video + Audio / Video + + + + System + System + + + + Enable desktop notifications + Desktop-Benachrichtigungen aktivieren + + + + Keep minimized on close + Beim Schließen minimiert bleiben + + + + Download folder + Ordner herunterladen + + + + Save in + Speichern in + + + + Always Recording + Immer aufzeichnen + + + + Updates + Aktualisierungen + + + + Check for updates automatically every + Automatisch auf Aktualisierungen prüfen. Alle + + + + Interval between update checks in days selector + Intervall zwischen Prüfung auf Aktualisierung in Tagen Wähler + + + + days + Tage + + + + Check for updates now button + Jetzt auf Aktualisierung prüfen Button + + + + Check for updates now + Aktualisieren + + + + Password + Passwort + + + + + Enable + Aktivieren + + + + toggle enable notifications + Benachrichtigungen aktivieren umschalten + + + + Toggle keep minimized on close + Beim Schließen minimiert bleiben umschalten + + + + Call Recordings + Anrufaufzeichnungen + + + + Toggle automatic updates + Automatische Aktualisierungen umschalten + + + + Jami Account + Jami-Konto + + + + + Profile + Profil + + + + + Identity + Identität + + + + Id + Id + + + + Registered name + Registrierter Name + + + + Type here to register a username + Hier zu registrierenden Benutzernamen eingeben + + + + Register + Registrieren + + + + Change Password + Passwort ändern + + + + Export Account + Konten exportieren + + + + + Delete Account + Konto löschen + + + + Linked Devices + Verbundene Geräte + + + + Link Another Device + Weiteres Gerät verknüpfen + + + + Banned Contacts + Gesperrte Kontakte + + + + Format + Format + + + + Video device framerate selector + Videogerät Framerate Wähler + + + + Preview unavailable + Keine Vorschau verfügbar + + + + + Advanced Account Settings + Erweiterte Kontoeinstellungen + + + + SIP Account + SIP-Konto + + + + Username + Benutzername + + + + Hostname + Rechnername + + + + Proxy + Proxy + + + + Audio + Audio + + + + Microphone + Mikrofon + + + + Audio input device selector + Audioeingabegeräte Wähler + + + + Output Device + Ausgabegerät + + + + Choose the output device + Wählen Sie ein Ausgabegerät + + + + Video + Video + + + + Device + Gerät + + + + Video device selector + Videogerät Wähler + + + + A registered name should not have any spaces and must be at least three letters long + Ein registrierter Name sollte keine Leerzeichen beinhalten und muss mindestens drei Zeichen lang sein + + + + This name is already taken + Dieser Benutzername ist bereits vergeben + + + + + Enter an alias + Aliasnamen eingeben + + + + Register this name + Diesen Namen registrieren + + + + Remove Device + Gerät entfernen + + + + Enter this account's password to confirm the removal of this device + Geben Sie das Kontopasswort ein um die Trennung dieses Gerätes zu bestätigen + + + + Are you sure you wish to remove this device? + Sicher, dass Sie das Gerät trennen wollen? + + + + Export Account Here + Konto hier exportieren + + + + Select A Folder For Your Downloads + Wählen Sie einen Ordner für ihre Downloads aus + + + + Select A Folder For Your Recordings + Wählen Sie einen Ordner für ihre Aufnahmen aus + + + + VideoOverlay + + + Call on Hold + Anruf pausiert + + + + Hold / Unhold + Pause / Fortsetzen + + + + Chat + Chat + + + + Mute Mic + Mikrofon stummschalten + + + + Record call + Anruf aufzeichnen + + + + Name label + Namenslabel + + + + Time elapsed + Zeit vergangen + + + + 00:00 + 00:00 + + + + Hangup + Auflegen + + + + Mute Video + Video stummschalten + + + + VideoView + + + Share entire screen + Gesamten Bildschirm teilen + + + + Share screen area + Bildschirmbereich teilen + + + + Share file + Datei teilen + + + \ No newline at end of file diff --git a/translations/ring_client_windows_de_DE.ts b/translations/ring_client_windows_de_DE.ts new file mode 100644 index 00000000..864bd382 --- /dev/null +++ b/translations/ring_client_windows_de_DE.ts @@ -0,0 +1,1589 @@ + + + AboutDialog + + + + About + Über + + + + about button + + + + + credits button + + + + + Credits + Abspann + + + + Free as in Freedom + + + + + The Microsoft Windows client for Jami. +Jami is a secured and distributed communication software. + + + + + version + Version + + + + Created by: + + + + + Artwork by: + + + + + Based on the SFLPhone project + + + + + AccountItemDelegate + + + Add Account + + + + + AdvancedSIPSettingsWidget + + + Form + + + + + Call Settings + + + + + Auto Answer Calls + + + + + Enable Custom Ringtone + + + + + Connectivity + Verbindung + + + + STUN Address + + + + + Use STUN + + + + + Use UPnP + + + + + Use TURN + TURN benutzen + + + + TURN Password + + + + + TURN Username + + + + + TURN Address + + + + + Media + Media + + + + Enable Video + Video aktivieren + + + + Video Codecs + + + + + Audio Codecs + + + + + Audio Files (*.wav *.ogg *.opus *.mp3 *aiff *wma) + + + + + Add a custom ringtone + + + + + AdvancedSettingsWidget + + + Form + + + + + Call Settings + + + + + Allow Calls From Untrusted Peers + + + + + Auto Answer Calls + + + + + Enable Custom Ringtone + + + + + Add a custom ringtone + + + + + Name Server + + + + + Address + + + + + OpenDHT Configuration + + + + + Enable Proxy + + + + + Bootstrap + Bootstrap + + + + Security + Sicherheit + + + + Private Key Password + Kennwort für privaten Schlüssel + + + + User Certificate + Benutzerzertifikat + + + + Private Key + + + + + CA Certificate + + + + + Connectivity + Verbindung + + + + Use STUN + + + + + STUN Address + + + + + Use UPnP + + + + + Use TURN + TURN benutzen + + + + TURN Password + + + + + TURN Username + + + + + TURN Address + + + + + Media + Media + + + + Enable Video + Video aktivieren + + + + Audio Codecs + + + + + Video Codecs + + + + + Audio Files (*.wav *.ogg *.opus *.mp3 *aiff *wma) + + + + + AnimatedOverlay + + + Form + + + + + BannedItemWidget + + + Form + + + + + name + + + + + id + + + + + CallWidget + + + Show conversations + + + + + Conversations + Gespräche + + + + Search contact text input + + + + + Jami is free software for universal communication which respects the freedoms and privacy of its users. + Jami ist Freie Software für universelle Kommunikation, die die Freiheiten und die Privatsphäre ihrer Nutzer respektiert. + + + + + This is your ID. +Copy and share it with your friends! + + + + + + Show ring ID QR code + + + + + Share ring ID button + + + + + Double-click to copy + + + + + Error while generating QR Code + Fehler beim Erzeugen des QR-Codes + + + + + best name + + + + + best Id + + + + + Back to homepage button + + + + + Add to contacts + Kontakte hinzufügen + + + + Show invites + + + + + Invites + + + + + + Find a new or existing contact + + + + + Wants to talk to you! + + + + + Answer incoming call button + + + + + Ignore incoming call button + + + + + Answer + Antwort + + + + Ignore + + + + + Cancel outgoing call + + + + + Cancel + Abbrechen + + + + Start video call + + + + + Start audio call + + + + + Clear conversation + + + + + Remove contact + + + + + Block contact + Kontakt blockieren + + + + Copy number + Nummer kopieren + + + + Search your received invitations + + + + + Contact me on Jami + + + + + My Id is : + + + + + %1 + %1 is the contact username + + + + + %1 + %1 is the contact unique identifier + + + + + Call incoming from %1 + + + + + DeleteAccountDialog + + + Account deletion + + + + + Do you really want to delete the following account? + + + + + If this account hasn't been exported, or added to another device, it will be irrevocably lost. + + + + + Permanently delete account + + + + + Delete + Löschen + + + + Cancel account deletion + + + + + Cancel + Abbrechen + + + + DeviceItemWidget + + + Form + + + + + Device Id + + + + + this device + dieses Gerät + + + + InviteButtonsWidget + + + Accept + Akzeptieren + + + + Refuse + Ablehnen + + + + Block + Blockieren + + + + LinkDeviceDialog + + + Dialog + + + + + Enter your account password + + + + + Password + Kennwort + + + + Ok + Ok + + + + Cancel + Abbrechen + + + + Exporting account + Konto wird exportiert + + + + Your PIN is + + + + + PIN + PIN + + + + This pin and the account password should be entered in your device within 10 minutes. + + + + + Close + Schließen + + + + Link Another Device + + + + + Incorrect password + + + + + Something went wrong. +Please try again later. + + + + + MainWindow + + + Settings + Einstellungen + + + + Exit + + + + + About + Über + + + + Jami + + + + + NameRegistrationDialog + + + Set Registered Name + + + + + Enter your account password + + + + + Password text input + + + + + Password text entry + + + + + Password + Kennwort + + + + Register + Registrieren + + + + Cancel + Abbrechen + + + + Registering Name + + + + + Something went wrong + + + + + Close + Schließen + + + + Incorrect password + + + + + Network error + Netzwerkfehler + + + + NewWizardWidget + + + Form + + + + + Welcome Label + + + + + Welcome to + + + + + Welcome Logo + + + + + Create Jami account button + + + + + Push button for Jami account creation start trigger + + + + + Create a Jami account + Jami-Konto erstellen + + + + Link device button + + + + + Push button for device linkage start trigger + + + + + Link this device to an account + Dieses Gerät mit einem bestehenden Konto verknüpfen + + + + Create Jami SIP account button + + + + + Push button for Jami SIP account creation start trigger + + + + + Create a SIP account + + + + + Link this device to an existing account + Dieses Gerät mit einem bestehenden Konto verknüpfen + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Ubuntu'; font-size:14px; color:#555555;">To link this device to another account, you first </span><span style=" font-family:'Ubuntu'; font-size:14px; font-weight:600; color:#555555;">need to obtain a PIN</span><span style=" font-family:'Ubuntu'; font-size:14px; color:#555555;"> code. To generate the PIN code:</span></p> +<ol style="margin-top: 0px; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; -qt-list-indent: 1;"><li style=" font-family:'Ubuntu'; font-size:14px; color:#555555;" style=" margin-top:12px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:14px;">Go to the </span><span style=" font-size:14px; font-weight:600;">Account management setting</span><span style=" font-size:14px;"> of a previous device</span></li> +<li style=" font-family:'Ubuntu'; font-size:14px; color:#555555;" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:14px;">Choose the </span><span style=" font-size:14px; font-weight:600;">Jami account</span><span style=" font-size:14px;"> you want to use</span></li> +<li style=" font-family:'Ubuntu'; font-size:14px; color:#555555;" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:14px;">Go to the </span><span style=" font-size:14px; font-weight:600;">Devices</span><span style=" font-size:14px;"> tab</span></li> +<li style=" font-family:'Ubuntu'; font-size:14px; color:#555555;" style=" margin-top:0px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:14px;">Select </span><span style=" font-size:14px; font-weight:600;">Add a device</span></li></ol> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Ubuntu'; font-size:14px; color:#555555;">You will get the necessary PIN to complete this form. The PIN is only valid for </span><span style=" font-family:'Ubuntu'; font-size:14px; font-weight:600; color:#555555;">10 minutes</span><span style=" font-family:'Ubuntu'; font-size:10px; color:#555555;">.</span></p></body></html> + + + + + Enter your pin: + PIN eingeben: + + + + Or import a file: + + + + + Link from exported account archive file + + + + + + + (None) + + + + + Password: + Kennwort: + + + + + Profile + Profil + + + + + Profile name + + + + + Account + Konto + + + + Register your username. +This will reserve the username so that only you can use it. +Your friends will be able to call you with your usename +instead of using your ID. + + + + + Public username checkbox + + + + + Checkbox selecting if the user wants a public username + + + + + Register public username + + + + + Public username edit + + + + + Choose your username + + + + + Password text input + + + + + Password text entry + + + + + + Password + Kennwort + + + + + Password confirmation text input + + + + + Confirm password + Konto bestätigen + + + + SIP Account + + + + + SIP Server edit + + + + + Server + + + + + SIP proxy input + + + + + SIP proxy text entry + + + + + Proxy + Proxy + + + + SIP username input + + + + + SIP Password text entry + + + + + Username + Benutzername + + + + + SIP Password text input + + + + + Generating your Jami account… + Ihr Jami-Konto wird erstellt … + + + + Previous page button + + + + + push button to access previous page of wizard + + + + + Previous + + + + + Cancel account create/link + + + + + push button to cancel account creation or linking + + + + + Back + Zurück + + + + Next page Button + + + + + Push button to access next page of wizard + + + + + Next + Weiter + + + + Open File + + + + + Jami archive files (*.gz); All files (*) + + + + + Your account needs to be migrated. Enter your password. + + + + + Migrating your Jami account... + + + + + Importing account archive... + + + + + Generating your Jami account... + + + + + Generating your SIP account... + + + + + Error creating account + + + + + PasswordDialog + + + Change Account Password + + + + + Enter Current Password + + + + + Enter New Password + + + + + Confirm New Password + + + + + Confirm + + + + + Cancel + Abbrechen + + + + Current Password Incorrect + + + + + PhotoBoothDialog + + + Photobooth + + + + + PhotoboothWidget + + + Form + + + + + Photobooth display + + + + + Choose File + + + + + Image Files (*.jpg *.jpeg *.png) + + + + + PrivateBridging + + + Choose File + + + + + Files (*) + + + + + QObject + + + No default mail client found + + + + + + Edit Device Name + + + + + Unlink Device From Account + + + + + Save new device name + + + + + Add as contact + + + + + RingButton + + + Select folder + + + + + SettingsWidget + + + Form + + + + + Settings + Einstellungen + + + + Account + Konto + + + + + General + Allgemein + + + + + Audio / Video + + + + + System + System + + + + Enable desktop notifications + + + + + Keep minimized on close + + + + + Download folder + Download-Ordner + + + + Save in + + + + + Always Recording + + + + + Updates + + + + + Check for updates automatically every + + + + + Interval between update checks in days selector + + + + + days + + + + + Check for updates now button + + + + + Check for updates now + + + + + Password + Kennwort + + + + + Enable + + + + + toggle enable notifications + + + + + Toggle keep minimized on close + + + + + Call Recordings + + + + + Toggle automatic updates + + + + + Jami Account + + + + + + Profile + Profil + + + + + Identity + + + + + Id + + + + + Registered name + + + + + Type here to register a username + + + + + Register + Registrieren + + + + Change Password + Ändere das Passwort + + + + Export Account + + + + + + Delete Account + + + + + Linked Devices + + + + + Link Another Device + + + + + Banned Contacts + + + + + Format + + + + + Video device framerate selector + + + + + Preview unavailable + + + + + + Advanced Account Settings + + + + + SIP Account + + + + + Username + Benutzername + + + + Hostname + Hostname + + + + Proxy + Proxy + + + + Audio + Audio + + + + Microphone + + + + + Audio input device selector + + + + + Output Device + + + + + Choose the output device + + + + + Video + Video + + + + Device + Gerät + + + + Video device selector + + + + + A registered name should not have any spaces and must be at least three letters long + + + + + This name is already taken + + + + + + Enter an alias + + + + + Register this name + + + + + Remove Device + + + + + Enter this account's password to confirm the removal of this device + + + + + Are you sure you wish to remove this device? + + + + + Export Account Here + + + + + Select A Folder For Your Downloads + + + + + Select A Folder For Your Recordings + + + + + VideoOverlay + + + Call on Hold + + + + + Hold / Unhold + + + + + Chat + Chat + + + + Mute Mic + + + + + Record call + + + + + Name label + + + + + Time elapsed + + + + + 00:00 + 00:00 + + + + Hangup + Auflegen + + + + Mute Video + + + + + VideoView + + + Share entire screen + + + + + Share screen area + + + + + Share file + Datei teilen + + + \ No newline at end of file diff --git a/translations/ring_client_windows_el.ts b/translations/ring_client_windows_el.ts new file mode 100644 index 00000000..8408e2fd --- /dev/null +++ b/translations/ring_client_windows_el.ts @@ -0,0 +1,1589 @@ + + + AboutDialog + + + + About + Περί + + + + about button + + + + + credits button + + + + + Credits + Μονάδες + + + + Free as in Freedom + + + + + The Microsoft Windows client for Jami. +Jami is a secured and distributed communication software. + + + + + version + έκδοση + + + + Created by: + + + + + Artwork by: + + + + + Based on the SFLPhone project + + + + + AccountItemDelegate + + + Add Account + + + + + AdvancedSIPSettingsWidget + + + Form + + + + + Call Settings + + + + + Auto Answer Calls + + + + + Enable Custom Ringtone + + + + + Connectivity + + + + + STUN Address + + + + + Use STUN + Χρήση STUN + + + + Use UPnP + + + + + Use TURN + Χρήση TURN + + + + TURN Password + + + + + TURN Username + + + + + TURN Address + + + + + Media + Μέσα + + + + Enable Video + Ενεργοποίση βίνταο + + + + Video Codecs + Κωδικοποιητές βίντεο + + + + Audio Codecs + Κωδικοποιητές ήχου + + + + Audio Files (*.wav *.ogg *.opus *.mp3 *aiff *wma) + + + + + Add a custom ringtone + + + + + AdvancedSettingsWidget + + + Form + + + + + Call Settings + + + + + Allow Calls From Untrusted Peers + + + + + Auto Answer Calls + + + + + Enable Custom Ringtone + + + + + Add a custom ringtone + + + + + Name Server + + + + + Address + Διεύθυνση + + + + OpenDHT Configuration + + + + + Enable Proxy + + + + + Bootstrap + + + + + Security + Ασφάλεια + + + + Private Key Password + + + + + User Certificate + + + + + Private Key + + + + + CA Certificate + + + + + Connectivity + + + + + Use STUN + Χρήση STUN + + + + STUN Address + + + + + Use UPnP + + + + + Use TURN + Χρήση TURN + + + + TURN Password + + + + + TURN Username + + + + + TURN Address + + + + + Media + Μέσα + + + + Enable Video + Ενεργοποίση βίνταο + + + + Audio Codecs + Κωδικοποιητές ήχου + + + + Video Codecs + Κωδικοποιητές βίντεο + + + + Audio Files (*.wav *.ogg *.opus *.mp3 *aiff *wma) + + + + + AnimatedOverlay + + + Form + + + + + BannedItemWidget + + + Form + + + + + name + + + + + id + + + + + CallWidget + + + Show conversations + + + + + Conversations + Συνομιλίες + + + + Search contact text input + + + + + Jami is free software for universal communication which respects the freedoms and privacy of its users. + + + + + + This is your ID. +Copy and share it with your friends! + + + + + + Show ring ID QR code + + + + + Share ring ID button + + + + + Double-click to copy + + + + + Error while generating QR Code + + + + + + best name + + + + + best Id + + + + + Back to homepage button + + + + + Add to contacts + Προσθήκη στις επαφές + + + + Show invites + + + + + Invites + + + + + + Find a new or existing contact + + + + + Wants to talk to you! + + + + + Answer incoming call button + + + + + Ignore incoming call button + + + + + Answer + + + + + Ignore + + + + + Cancel outgoing call + + + + + Cancel + Ακύρωση + + + + Start video call + + + + + Start audio call + + + + + Clear conversation + + + + + Remove contact + + + + + Block contact + + + + + Copy number + Αντιγραφή αριθμού + + + + Search your received invitations + + + + + Contact me on Jami + + + + + My Id is : + + + + + %1 + %1 is the contact username + + + + + %1 + %1 is the contact unique identifier + + + + + Call incoming from %1 + + + + + DeleteAccountDialog + + + Account deletion + + + + + Do you really want to delete the following account? + + + + + If this account hasn't been exported, or added to another device, it will be irrevocably lost. + + + + + Permanently delete account + + + + + Delete + Διαγραφή + + + + Cancel account deletion + + + + + Cancel + Ακύρωση + + + + DeviceItemWidget + + + Form + + + + + Device Id + + + + + this device + + + + + InviteButtonsWidget + + + Accept + Αποδοχή + + + + Refuse + Άρνηση + + + + Block + Μπλοκάρισμα + + + + LinkDeviceDialog + + + Dialog + + + + + Enter your account password + + + + + Password + Συνθηματικό + + + + Ok + Εντάξει + + + + Cancel + Ακύρωση + + + + Exporting account + + + + + Your PIN is + + + + + PIN + + + + + This pin and the account password should be entered in your device within 10 minutes. + + + + + Close + Κλείσιμο + + + + Link Another Device + + + + + Incorrect password + + + + + Something went wrong. +Please try again later. + + + + + MainWindow + + + Settings + Ρυθμίσεις + + + + Exit + Έξοδος + + + + About + Περί + + + + Jami + + + + + NameRegistrationDialog + + + Set Registered Name + + + + + Enter your account password + + + + + Password text input + + + + + Password text entry + + + + + Password + Συνθηματικό + + + + Register + Εγγραφή + + + + Cancel + Ακύρωση + + + + Registering Name + + + + + Something went wrong + + + + + Close + Κλείσιμο + + + + Incorrect password + + + + + Network error + Σφάλμα δικτύου + + + + NewWizardWidget + + + Form + + + + + Welcome Label + + + + + Welcome to + + + + + Welcome Logo + + + + + Create Jami account button + + + + + Push button for Jami account creation start trigger + + + + + Create a Jami account + + + + + Link device button + + + + + Push button for device linkage start trigger + + + + + Link this device to an account + Σύνδεση αυτής της συσκευής με ένα λογαριασμό + + + + Create Jami SIP account button + + + + + Push button for Jami SIP account creation start trigger + + + + + Create a SIP account + + + + + Link this device to an existing account + Σύνδεση αυτής της συσκευής σε έναν λογαριασμό που ήδη υπάρχει + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Ubuntu'; font-size:14px; color:#555555;">To link this device to another account, you first </span><span style=" font-family:'Ubuntu'; font-size:14px; font-weight:600; color:#555555;">need to obtain a PIN</span><span style=" font-family:'Ubuntu'; font-size:14px; color:#555555;"> code. To generate the PIN code:</span></p> +<ol style="margin-top: 0px; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; -qt-list-indent: 1;"><li style=" font-family:'Ubuntu'; font-size:14px; color:#555555;" style=" margin-top:12px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:14px;">Go to the </span><span style=" font-size:14px; font-weight:600;">Account management setting</span><span style=" font-size:14px;"> of a previous device</span></li> +<li style=" font-family:'Ubuntu'; font-size:14px; color:#555555;" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:14px;">Choose the </span><span style=" font-size:14px; font-weight:600;">Jami account</span><span style=" font-size:14px;"> you want to use</span></li> +<li style=" font-family:'Ubuntu'; font-size:14px; color:#555555;" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:14px;">Go to the </span><span style=" font-size:14px; font-weight:600;">Devices</span><span style=" font-size:14px;"> tab</span></li> +<li style=" font-family:'Ubuntu'; font-size:14px; color:#555555;" style=" margin-top:0px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:14px;">Select </span><span style=" font-size:14px; font-weight:600;">Add a device</span></li></ol> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Ubuntu'; font-size:14px; color:#555555;">You will get the necessary PIN to complete this form. The PIN is only valid for </span><span style=" font-family:'Ubuntu'; font-size:14px; font-weight:600; color:#555555;">10 minutes</span><span style=" font-family:'Ubuntu'; font-size:10px; color:#555555;">.</span></p></body></html> + + + + + Enter your pin: + Εισάγετε το PIN σας: + + + + Or import a file: + + + + + Link from exported account archive file + + + + + + + (None) + + + + + Password: + Συνθηματικό: + + + + + Profile + Προφίλ + + + + + Profile name + + + + + Account + Λογαριασμός + + + + Register your username. +This will reserve the username so that only you can use it. +Your friends will be able to call you with your usename +instead of using your ID. + + + + + Public username checkbox + + + + + Checkbox selecting if the user wants a public username + + + + + Register public username + Καταχώρηση δημόσιου ονόματος χρήστη + + + + Public username edit + + + + + Choose your username + + + + + Password text input + + + + + Password text entry + + + + + + Password + Συνθηματικό + + + + + Password confirmation text input + + + + + Confirm password + + + + + SIP Account + + + + + SIP Server edit + + + + + Server + + + + + SIP proxy input + + + + + SIP proxy text entry + + + + + Proxy + Διαμεσολαβητής + + + + SIP username input + + + + + SIP Password text entry + + + + + Username + Όνομα χρήστη + + + + + SIP Password text input + + + + + Generating your Jami account… + + + + + Previous page button + + + + + push button to access previous page of wizard + + + + + Previous + Προηγούμενο + + + + Cancel account create/link + + + + + push button to cancel account creation or linking + + + + + Back + Πίσω + + + + Next page Button + + + + + Push button to access next page of wizard + + + + + Next + Επόμενο + + + + Open File + Άνοιγμα αρχείου + + + + Jami archive files (*.gz); All files (*) + + + + + Your account needs to be migrated. Enter your password. + + + + + Migrating your Jami account... + + + + + Importing account archive... + + + + + Generating your Jami account... + + + + + Generating your SIP account... + + + + + Error creating account + + + + + PasswordDialog + + + Change Account Password + + + + + Enter Current Password + + + + + Enter New Password + + + + + Confirm New Password + + + + + Confirm + + + + + Cancel + Ακύρωση + + + + Current Password Incorrect + + + + + PhotoBoothDialog + + + Photobooth + + + + + PhotoboothWidget + + + Form + + + + + Photobooth display + + + + + Choose File + + + + + Image Files (*.jpg *.jpeg *.png) + + + + + PrivateBridging + + + Choose File + + + + + Files (*) + + + + + QObject + + + No default mail client found + + + + + + Edit Device Name + + + + + Unlink Device From Account + + + + + Save new device name + + + + + Add as contact + + + + + RingButton + + + Select folder + + + + + SettingsWidget + + + Form + + + + + Settings + Ρυθμίσεις + + + + Account + Λογαριασμός + + + + + General + Γενικά + + + + + Audio / Video + + + + + System + Σύστημα + + + + Enable desktop notifications + + + + + Keep minimized on close + + + + + Download folder + + + + + Save in + Αποθήκευση σε + + + + Always Recording + + + + + Updates + + + + + Check for updates automatically every + + + + + Interval between update checks in days selector + + + + + days + + + + + Check for updates now button + + + + + Check for updates now + + + + + Password + Συνθηματικό + + + + + Enable + + + + + toggle enable notifications + + + + + Toggle keep minimized on close + + + + + Call Recordings + + + + + Toggle automatic updates + + + + + Jami Account + + + + + + Profile + Προφίλ + + + + + Identity + + + + + Id + + + + + Registered name + + + + + Type here to register a username + + + + + Register + Εγγραφή + + + + Change Password + + + + + Export Account + + + + + + Delete Account + + + + + Linked Devices + + + + + Link Another Device + + + + + Banned Contacts + + + + + Format + + + + + Video device framerate selector + + + + + Preview unavailable + + + + + + Advanced Account Settings + + + + + SIP Account + + + + + Username + Όνομα χρήστη + + + + Hostname + Hostname + + + + Proxy + Διαμεσολαβητής + + + + Audio + Ήχος + + + + Microphone + + + + + Audio input device selector + + + + + Output Device + + + + + Choose the output device + + + + + Video + Βίντεο + + + + Device + Συσκευή + + + + Video device selector + + + + + A registered name should not have any spaces and must be at least three letters long + + + + + This name is already taken + + + + + + Enter an alias + + + + + Register this name + + + + + Remove Device + + + + + Enter this account's password to confirm the removal of this device + + + + + Are you sure you wish to remove this device? + + + + + Export Account Here + + + + + Select A Folder For Your Downloads + + + + + Select A Folder For Your Recordings + + + + + VideoOverlay + + + Call on Hold + + + + + Hold / Unhold + + + + + Chat + Συνομιλία + + + + Mute Mic + + + + + Record call + + + + + Name label + + + + + Time elapsed + + + + + 00:00 + + + + + Hangup + + + + + Mute Video + + + + + VideoView + + + Share entire screen + + + + + Share screen area + Μοίρασμα περιοχής της οθόνης + + + + Share file + Μοίρασμα αρχείου + + + \ No newline at end of file diff --git a/translations/ring_client_windows_en_GB.ts b/translations/ring_client_windows_en_GB.ts new file mode 100644 index 00000000..79dc3933 --- /dev/null +++ b/translations/ring_client_windows_en_GB.ts @@ -0,0 +1,1591 @@ + + + + + AboutDialog + + + + About + + + + + about button + + + + + credits button + + + + + Credits + + + + + Free as in Freedom + + + + + The Microsoft Windows client for Jami. +Jami is a secured and distributed communication software. + + + + + version + + + + + Created by: + + + + + Artwork by: + + + + + Based on the SFLPhone project + + + + + AccountItemDelegate + + + Add Account + + + + + AdvancedSIPSettingsWidget + + + Form + + + + + Call Settings + + + + + Auto Answer Calls + + + + + Enable Custom Ringtone + + + + + Connectivity + + + + + STUN Address + + + + + Use STUN + + + + + Use UPnP + + + + + Use TURN + + + + + TURN Password + + + + + TURN Username + + + + + TURN Address + + + + + Media + + + + + Enable Video + + + + + Video Codecs + + + + + Audio Codecs + + + + + Audio Files (*.wav *.ogg *.opus *.mp3 *aiff *wma) + + + + + Add a custom ringtone + + + + + AdvancedSettingsWidget + + + Form + + + + + Call Settings + + + + + Allow Calls From Untrusted Peers + + + + + Auto Answer Calls + + + + + Enable Custom Ringtone + + + + + Add a custom ringtone + + + + + Name Server + + + + + Address + + + + + OpenDHT Configuration + + + + + Enable Proxy + + + + + Bootstrap + + + + + Security + + + + + Private Key Password + + + + + User Certificate + + + + + Private Key + + + + + CA Certificate + + + + + Connectivity + + + + + Use STUN + + + + + STUN Address + + + + + Use UPnP + + + + + Use TURN + + + + + TURN Password + + + + + TURN Username + + + + + TURN Address + + + + + Media + + + + + Enable Video + + + + + Audio Codecs + + + + + Video Codecs + + + + + Audio Files (*.wav *.ogg *.opus *.mp3 *aiff *wma) + + + + + AnimatedOverlay + + + Form + + + + + BannedItemWidget + + + Form + + + + + name + + + + + id + + + + + CallWidget + + + Show conversations + + + + + Conversations + + + + + Search contact text input + + + + + Jami is free software for universal communication which respects the freedoms and privacy of its users. + + + + + + This is your ID. +Copy and share it with your friends! + + + + + + Show ring ID QR code + + + + + Share ring ID button + + + + + Double-click to copy + + + + + Error while generating QR Code + + + + + + best name + + + + + best Id + + + + + Back to homepage button + + + + + Add to contacts + + + + + Show invites + + + + + Invites + + + + + + Find a new or existing contact + + + + + Wants to talk to you! + + + + + Answer incoming call button + + + + + Ignore incoming call button + + + + + Answer + + + + + Ignore + + + + + Cancel outgoing call + + + + + Cancel + + + + + Start video call + + + + + Start audio call + + + + + Clear conversation + + + + + Remove contact + + + + + Block contact + + + + + Copy number + + + + + Search your received invitations + + + + + Contact me on Jami + + + + + My Id is : + + + + + %1 + %1 is the contact username + + + + + %1 + %1 is the contact unique identifier + + + + + Call incoming from %1 + + + + + DeleteAccountDialog + + + Account deletion + + + + + Do you really want to delete the following account? + + + + + If this account hasn't been exported, or added to another device, it will be irrevocably lost. + + + + + Permanently delete account + + + + + Delete + + + + + Cancel account deletion + + + + + Cancel + + + + + DeviceItemWidget + + + Form + + + + + Device Id + + + + + this device + + + + + InviteButtonsWidget + + + Accept + + + + + Refuse + + + + + Block + + + + + LinkDeviceDialog + + + Dialog + + + + + Enter your account password + + + + + Password + + + + + Ok + + + + + Cancel + + + + + Exporting account + + + + + Your PIN is + + + + + PIN + + + + + This pin and the account password should be entered in your device within 10 minutes. + + + + + Close + + + + + Link Another Device + + + + + Incorrect password + + + + + Something went wrong. +Please try again later. + + + + + MainWindow + + + Settings + + + + + Exit + + + + + About + + + + + Jami + + + + + NameRegistrationDialog + + + Set Registered Name + + + + + Enter your account password + + + + + Password text input + + + + + Password text entry + + + + + Password + + + + + Register + + + + + Cancel + + + + + Registering Name + + + + + Something went wrong + + + + + Close + + + + + Incorrect password + + + + + Network error + + + + + NewWizardWidget + + + Form + + + + + Welcome Label + + + + + Welcome to + + + + + Welcome Logo + + + + + Create Jami account button + + + + + Push button for Jami account creation start trigger + + + + + Create a Jami account + + + + + Link device button + + + + + Push button for device linkage start trigger + + + + + Link this device to an account + + + + + Create Jami SIP account button + + + + + Push button for Jami SIP account creation start trigger + + + + + Create a SIP account + + + + + Link this device to an existing account + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Ubuntu'; font-size:14px; color:#555555;">To link this device to another account, you first </span><span style=" font-family:'Ubuntu'; font-size:14px; font-weight:600; color:#555555;">need to obtain a PIN</span><span style=" font-family:'Ubuntu'; font-size:14px; color:#555555;"> code. To generate the PIN code:</span></p> +<ol style="margin-top: 0px; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; -qt-list-indent: 1;"><li style=" font-family:'Ubuntu'; font-size:14px; color:#555555;" style=" margin-top:12px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:14px;">Go to the </span><span style=" font-size:14px; font-weight:600;">Account management setting</span><span style=" font-size:14px;"> of a previous device</span></li> +<li style=" font-family:'Ubuntu'; font-size:14px; color:#555555;" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:14px;">Choose the </span><span style=" font-size:14px; font-weight:600;">Jami account</span><span style=" font-size:14px;"> you want to use</span></li> +<li style=" font-family:'Ubuntu'; font-size:14px; color:#555555;" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:14px;">Go to the </span><span style=" font-size:14px; font-weight:600;">Devices</span><span style=" font-size:14px;"> tab</span></li> +<li style=" font-family:'Ubuntu'; font-size:14px; color:#555555;" style=" margin-top:0px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:14px;">Select </span><span style=" font-size:14px; font-weight:600;">Add a device</span></li></ol> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Ubuntu'; font-size:14px; color:#555555;">You will get the necessary PIN to complete this form. The PIN is only valid for </span><span style=" font-family:'Ubuntu'; font-size:14px; font-weight:600; color:#555555;">10 minutes</span><span style=" font-family:'Ubuntu'; font-size:10px; color:#555555;">.</span></p></body></html> + + + + + Enter your pin: + + + + + Or import a file: + + + + + Link from exported account archive file + + + + + + + (None) + + + + + Password: + + + + + + Profile + + + + + + Profile name + + + + + Account + + + + + Register your username. +This will reserve the username so that only you can use it. +Your friends will be able to call you with your usename +instead of using your ID. + + + + + Public username checkbox + + + + + Checkbox selecting if the user wants a public username + + + + + Register public username + + + + + Public username edit + + + + + Choose your username + + + + + Password text input + + + + + Password text entry + + + + + + Password + + + + + + Password confirmation text input + + + + + Confirm password + + + + + SIP Account + + + + + SIP Server edit + + + + + Server + + + + + SIP proxy input + + + + + SIP proxy text entry + + + + + Proxy + + + + + SIP username input + + + + + SIP Password text entry + + + + + Username + + + + + + SIP Password text input + + + + + Generating your Jami account… + + + + + Previous page button + + + + + push button to access previous page of wizard + + + + + Previous + + + + + Cancel account create/link + + + + + push button to cancel account creation or linking + + + + + Back + + + + + Next page Button + + + + + Push button to access next page of wizard + + + + + Next + + + + + Open File + + + + + Jami archive files (*.gz); All files (*) + + + + + Your account needs to be migrated. Enter your password. + + + + + Migrating your Jami account... + + + + + Importing account archive... + + + + + Generating your Jami account... + + + + + Generating your SIP account... + + + + + Error creating account + + + + + PasswordDialog + + + Change Account Password + + + + + Enter Current Password + + + + + Enter New Password + + + + + Confirm New Password + + + + + Confirm + + + + + Cancel + + + + + Current Password Incorrect + + + + + PhotoBoothDialog + + + Photobooth + + + + + PhotoboothWidget + + + Form + + + + + Photobooth display + + + + + Choose File + + + + + Image Files (*.jpg *.jpeg *.png) + + + + + PrivateBridging + + + Choose File + + + + + Files (*) + + + + + QObject + + + No default mail client found + + + + + + Edit Device Name + + + + + Unlink Device From Account + + + + + Save new device name + + + + + Add as contact + + + + + RingButton + + + Select folder + + + + + SettingsWidget + + + Form + + + + + Settings + + + + + Account + + + + + + General + + + + + + Audio / Video + + + + + System + + + + + Enable desktop notifications + + + + + Keep minimized on close + + + + + Download folder + + + + + Save in + + + + + Always Recording + + + + + Updates + + + + + Check for updates automatically every + + + + + Interval between update checks in days selector + + + + + days + + + + + Check for updates now button + + + + + Check for updates now + + + + + Password + + + + + + Enable + + + + + toggle enable notifications + + + + + Toggle keep minimized on close + + + + + Call Recordings + + + + + Toggle automatic updates + + + + + Jami Account + + + + + + Profile + + + + + + Identity + + + + + Id + + + + + Registered name + + + + + Type here to register a username + + + + + Register + + + + + Change Password + + + + + Export Account + + + + + + Delete Account + + + + + Linked Devices + + + + + Link Another Device + + + + + Banned Contacts + + + + + Format + + + + + Video device framerate selector + + + + + Preview unavailable + + + + + + Advanced Account Settings + + + + + SIP Account + + + + + Username + + + + + Hostname + + + + + Proxy + + + + + Audio + + + + + Microphone + + + + + Audio input device selector + + + + + Output Device + + + + + Choose the output device + + + + + Video + + + + + Device + + + + + Video device selector + + + + + A registered name should not have any spaces and must be at least three letters long + + + + + This name is already taken + + + + + + Enter an alias + + + + + Register this name + + + + + Remove Device + + + + + Enter this account's password to confirm the removal of this device + + + + + Are you sure you wish to remove this device? + + + + + Export Account Here + + + + + Select A Folder For Your Downloads + + + + + Select A Folder For Your Recordings + + + + + VideoOverlay + + + Call on Hold + + + + + Hold / Unhold + + + + + Chat + + + + + Mute Mic + + + + + Record call + + + + + Name label + + + + + Time elapsed + + + + + 00:00 + + + + + Hangup + + + + + Mute Video + + + + + VideoView + + + Share entire screen + + + + + Share screen area + + + + + Share file + + + + diff --git a/translations/ring_client_windows_eo.ts b/translations/ring_client_windows_eo.ts new file mode 100644 index 00000000..2a4dcc99 --- /dev/null +++ b/translations/ring_client_windows_eo.ts @@ -0,0 +1,1589 @@ + + + AboutDialog + + + + About + Pri + + + + about button + + + + + credits button + + + + + Credits + Kredito + + + + Free as in Freedom + + + + + The Microsoft Windows client for Jami. +Jami is a secured and distributed communication software. + + + + + version + versio + + + + Created by: + Kreita de: + + + + Artwork by: + Grafiko de: + + + + Based on the SFLPhone project + Surbaze de la SFLPhone projekto + + + + AccountItemDelegate + + + Add Account + + + + + AdvancedSIPSettingsWidget + + + Form + Form + + + + Call Settings + + + + + Auto Answer Calls + + + + + Enable Custom Ringtone + + + + + Connectivity + + + + + STUN Address + + + + + Use STUN + Uzi STUN + + + + Use UPnP + + + + + Use TURN + Uzi TURN + + + + TURN Password + + + + + TURN Username + + + + + TURN Address + + + + + Media + Aŭdvidaĵoj + + + + Enable Video + Ŝalti Videon + + + + Video Codecs + + + + + Audio Codecs + + + + + Audio Files (*.wav *.ogg *.opus *.mp3 *aiff *wma) + + + + + Add a custom ringtone + + + + + AdvancedSettingsWidget + + + Form + Form + + + + Call Settings + + + + + Allow Calls From Untrusted Peers + + + + + Auto Answer Calls + + + + + Enable Custom Ringtone + + + + + Add a custom ringtone + + + + + Name Server + + + + + Address + Adreso + + + + OpenDHT Configuration + + + + + Enable Proxy + + + + + Bootstrap + Praŝarĝo + + + + Security + Sekuro + + + + Private Key Password + Pasvorto de Privata Ŝlosilo + + + + User Certificate + Uzanta Atestilo + + + + Private Key + + + + + CA Certificate + + + + + Connectivity + + + + + Use STUN + Uzi STUN + + + + STUN Address + + + + + Use UPnP + + + + + Use TURN + Uzi TURN + + + + TURN Password + + + + + TURN Username + + + + + TURN Address + + + + + Media + Aŭdvidaĵoj + + + + Enable Video + Ŝalti Videon + + + + Audio Codecs + + + + + Video Codecs + + + + + Audio Files (*.wav *.ogg *.opus *.mp3 *aiff *wma) + + + + + AnimatedOverlay + + + Form + Form + + + + BannedItemWidget + + + Form + Form + + + + name + + + + + id + + + + + CallWidget + + + Show conversations + + + + + Conversations + Konversacioj + + + + Search contact text input + + + + + Jami is free software for universal communication which respects the freedoms and privacy of its users. + + + + + + This is your ID. +Copy and share it with your friends! + + + + + + Show ring ID QR code + + + + + Share ring ID button + + + + + Double-click to copy + + + + + Error while generating QR Code + Eraro dum generado de QR Kodo + + + + + best name + + + + + best Id + + + + + Back to homepage button + + + + + Add to contacts + Aldoni al kontaktoj + + + + Show invites + + + + + Invites + + + + + + Find a new or existing contact + + + + + Wants to talk to you! + Volas paroli kun vi! + + + + Answer incoming call button + + + + + Ignore incoming call button + + + + + Answer + Respondi + + + + Ignore + Malatenti + + + + Cancel outgoing call + + + + + Cancel + Rezigni + + + + Start video call + + + + + Start audio call + + + + + Clear conversation + + + + + Remove contact + + + + + Block contact + + + + + Copy number + Kopii numeron + + + + Search your received invitations + + + + + Contact me on Jami + + + + + My Id is : + + + + + %1 + %1 is the contact username + %1 + + + + %1 + %1 is the contact unique identifier + %1 + + + + Call incoming from %1 + Voko eniranta de %1 + + + + DeleteAccountDialog + + + Account deletion + + + + + Do you really want to delete the following account? + + + + + If this account hasn't been exported, or added to another device, it will be irrevocably lost. + + + + + Permanently delete account + + + + + Delete + Forigi + + + + Cancel account deletion + + + + + Cancel + Rezigni + + + + DeviceItemWidget + + + Form + Form + + + + Device Id + + + + + this device + + + + + InviteButtonsWidget + + + Accept + Akcepti + + + + Refuse + Rifuzi + + + + Block + + + + + LinkDeviceDialog + + + Dialog + Dialogo + + + + Enter your account password + + + + + Password + Pasvorto + + + + Ok + Okej + + + + Cancel + Rezigni + + + + Exporting account + Elportanta konton + + + + Your PIN is + + + + + PIN + PIN + + + + This pin and the account password should be entered in your device within 10 minutes. + + + + + Close + + + + + Link Another Device + + + + + Incorrect password + + + + + Something went wrong. +Please try again later. + + + + + MainWindow + + + Settings + Agordoj + + + + Exit + Eliri + + + + About + Pri + + + + Jami + + + + + NameRegistrationDialog + + + Set Registered Name + + + + + Enter your account password + + + + + Password text input + + + + + Password text entry + + + + + Password + Pasvorto + + + + Register + Registri + + + + Cancel + Rezigni + + + + Registering Name + + + + + Something went wrong + + + + + Close + + + + + Incorrect password + + + + + Network error + Reta eraro + + + + NewWizardWidget + + + Form + Form + + + + Welcome Label + + + + + Welcome to + + + + + Welcome Logo + + + + + Create Jami account button + + + + + Push button for Jami account creation start trigger + + + + + Create a Jami account + + + + + Link device button + + + + + Push button for device linkage start trigger + + + + + Link this device to an account + Ligi tiun aparaton al konto + + + + Create Jami SIP account button + + + + + Push button for Jami SIP account creation start trigger + + + + + Create a SIP account + + + + + Link this device to an existing account + Ligi ĉi tiun aparaton al ekzistanta konto + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Ubuntu'; font-size:14px; color:#555555;">To link this device to another account, you first </span><span style=" font-family:'Ubuntu'; font-size:14px; font-weight:600; color:#555555;">need to obtain a PIN</span><span style=" font-family:'Ubuntu'; font-size:14px; color:#555555;"> code. To generate the PIN code:</span></p> +<ol style="margin-top: 0px; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; -qt-list-indent: 1;"><li style=" font-family:'Ubuntu'; font-size:14px; color:#555555;" style=" margin-top:12px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:14px;">Go to the </span><span style=" font-size:14px; font-weight:600;">Account management setting</span><span style=" font-size:14px;"> of a previous device</span></li> +<li style=" font-family:'Ubuntu'; font-size:14px; color:#555555;" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:14px;">Choose the </span><span style=" font-size:14px; font-weight:600;">Jami account</span><span style=" font-size:14px;"> you want to use</span></li> +<li style=" font-family:'Ubuntu'; font-size:14px; color:#555555;" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:14px;">Go to the </span><span style=" font-size:14px; font-weight:600;">Devices</span><span style=" font-size:14px;"> tab</span></li> +<li style=" font-family:'Ubuntu'; font-size:14px; color:#555555;" style=" margin-top:0px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:14px;">Select </span><span style=" font-size:14px; font-weight:600;">Add a device</span></li></ol> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Ubuntu'; font-size:14px; color:#555555;">You will get the necessary PIN to complete this form. The PIN is only valid for </span><span style=" font-family:'Ubuntu'; font-size:14px; font-weight:600; color:#555555;">10 minutes</span><span style=" font-family:'Ubuntu'; font-size:10px; color:#555555;">.</span></p></body></html> + + + + + Enter your pin: + Entajpu vian PIN-on: + + + + Or import a file: + + + + + Link from exported account archive file + + + + + + + (None) + + + + + Password: + Pasvorto: + + + + + Profile + Profilo + + + + + Profile name + + + + + Account + Konto + + + + Register your username. +This will reserve the username so that only you can use it. +Your friends will be able to call you with your usename +instead of using your ID. + + + + + Public username checkbox + + + + + Checkbox selecting if the user wants a public username + + + + + Register public username + + + + + Public username edit + + + + + Choose your username + Elektu vian uzantnomon + + + + Password text input + + + + + Password text entry + + + + + + Password + Pasvorto + + + + + Password confirmation text input + + + + + Confirm password + Konfirmu pasvorton + + + + SIP Account + SIP Konto + + + + SIP Server edit + + + + + Server + + + + + SIP proxy input + + + + + SIP proxy text entry + + + + + Proxy + Prokura Servilo + + + + SIP username input + + + + + SIP Password text entry + + + + + Username + Uzantnomo + + + + + SIP Password text input + + + + + Generating your Jami account… + + + + + Previous page button + + + + + push button to access previous page of wizard + + + + + Previous + Antaŭa + + + + Cancel account create/link + + + + + push button to cancel account creation or linking + + + + + Back + + + + + Next page Button + + + + + Push button to access next page of wizard + + + + + Next + Sekva + + + + Open File + Malfermi Dosieron + + + + Jami archive files (*.gz); All files (*) + + + + + Your account needs to be migrated. Enter your password. + + + + + Migrating your Jami account... + + + + + Importing account archive... + + + + + Generating your Jami account... + + + + + Generating your SIP account... + + + + + Error creating account + + + + + PasswordDialog + + + Change Account Password + + + + + Enter Current Password + + + + + Enter New Password + + + + + Confirm New Password + + + + + Confirm + + + + + Cancel + Rezigni + + + + Current Password Incorrect + + + + + PhotoBoothDialog + + + Photobooth + Fotejo + + + + PhotoboothWidget + + + Form + Form + + + + Photobooth display + + + + + Choose File + Elektu dosieron + + + + Image Files (*.jpg *.jpeg *.png) + + + + + PrivateBridging + + + Choose File + Elektu dosieron + + + + Files (*) + Dosieroj (*) + + + + QObject + + + No default mail client found + Neniu defaŭlta retpoŝta kliento trovita + + + + + Edit Device Name + + + + + Unlink Device From Account + + + + + Save new device name + + + + + Add as contact + + + + + RingButton + + + Select folder + + + + + SettingsWidget + + + Form + Form + + + + Settings + Agordoj + + + + Account + Konto + + + + + General + Ĝeneralaj + + + + + Audio / Video + + + + + System + Sistemo + + + + Enable desktop notifications + + + + + Keep minimized on close + Ne ĉesu pro fermado fenestron + + + + Download folder + + + + + Save in + Konservi en + + + + Always Recording + + + + + Updates + + + + + Check for updates automatically every + + + + + Interval between update checks in days selector + + + + + days + + + + + Check for updates now button + + + + + Check for updates now + + + + + Password + Pasvorto + + + + + Enable + + + + + toggle enable notifications + + + + + Toggle keep minimized on close + + + + + Call Recordings + + + + + Toggle automatic updates + + + + + Jami Account + + + + + + Profile + Profilo + + + + + Identity + + + + + Id + + + + + Registered name + + + + + Type here to register a username + + + + + Register + Registri + + + + Change Password + + + + + Export Account + + + + + + Delete Account + + + + + Linked Devices + + + + + Link Another Device + + + + + Banned Contacts + + + + + Format + + + + + Video device framerate selector + + + + + Preview unavailable + + + + + + Advanced Account Settings + + + + + SIP Account + SIP Konto + + + + Username + Uzantnomo + + + + Hostname + Nomo de gastiga komputilo + + + + Proxy + Prokura Servilo + + + + Audio + Aŭdio + + + + Microphone + + + + + Audio input device selector + + + + + Output Device + Eliga aparato + + + + Choose the output device + + + + + Video + Video + + + + Device + Aparato + + + + Video device selector + + + + + A registered name should not have any spaces and must be at least three letters long + + + + + This name is already taken + + + + + + Enter an alias + + + + + Register this name + + + + + Remove Device + + + + + Enter this account's password to confirm the removal of this device + + + + + Are you sure you wish to remove this device? + + + + + Export Account Here + + + + + Select A Folder For Your Downloads + + + + + Select A Folder For Your Recordings + + + + + VideoOverlay + + + Call on Hold + Voko detenita + + + + Hold / Unhold + Deteni / Maldeteni + + + + Chat + Babilo + + + + Mute Mic + Selentigi Mikrofonon + + + + Record call + + + + + Name label + Noma etikedo + + + + Time elapsed + Pasinta tempo + + + + 00:00 + 00:00 + + + + Hangup + Fini Vokon + + + + Mute Video + Silentigi Videon + + + + VideoView + + + Share entire screen + Kunhavigi tutan ekranon + + + + Share screen area + Kunhavigi areon de ekrano + + + + Share file + Kunhavigi dosieron + + + \ No newline at end of file diff --git a/translations/ring_client_windows_es.ts b/translations/ring_client_windows_es.ts new file mode 100644 index 00000000..8dc04410 --- /dev/null +++ b/translations/ring_client_windows_es.ts @@ -0,0 +1,1605 @@ + + + AboutDialog + + + + About + Acerca de + + + + about button + Botón de Acerca de + + + + credits button + Botón de Créditos + + + + Credits + Créditos + + + + Free as in Freedom + Libre en el sentido de libertad + + + + The Microsoft Windows client for Jami. +Jami is a secured and distributed communication software. + El cliente de Jami para Microsoft Windows. +Jami es un software de comunicacion seguro y distribuído. + + + + version + versión + + + + Created by: + Creado por: + + + + Artwork by: + Diseñado por: + + + + Based on the SFLPhone project + Basado en el proyecto SFLPhone + + + + AccountItemDelegate + + + Add Account + Añadir cuenta + + + + AdvancedSIPSettingsWidget + + + Form + Formulario + + + + Call Settings + Configuración de llamada + + + + Auto Answer Calls + Auto-responder llamadas + + + + Enable Custom Ringtone + Activar configuración de timbre + + + + Connectivity + Conectividad + + + + STUN Address + Dirección STUN + + + + Use STUN + Utilizar STUN + + + + Use UPnP + Usar UPnP (Universal Plug and Play) + + + + Use TURN + Usar TURN + + + + TURN Password + Contraseña TURN + + + + TURN Username + Nombre de usuario TURN + + + + TURN Address + Dirección TURN + + + + Media + Medios + + + + Enable Video + Habilitar vídeo + + + + Video Codecs + Codecs de vídeo + + + + Audio Codecs + Codecs de audio + + + + Audio Files (*.wav *.ogg *.opus *.mp3 *aiff *wma) + Ficheros de audio (*.wav *.ogg *.opus *.mp3 *aiff *wma) + + + + Add a custom ringtone + Añadir un timbre a elección + + + + AdvancedSettingsWidget + + + Form + Formulario + + + + Call Settings + Configuración de llamada + + + + Allow Calls From Untrusted Peers + Permitir llamadas de pares desconocidos + + + + Auto Answer Calls + Auto-responder llamadas + + + + Enable Custom Ringtone + Activar configuración de timbre + + + + Add a custom ringtone + Añadir un timbre a elección + + + + Name Server + Nombrar Servidor + + + + Address + Dirección + + + + OpenDHT Configuration + Configuración de OpenDHT + + + + Enable Proxy + Habilitar proxy + + + + Bootstrap + Cargador de inicio + + + + Security + Seguridad + + + + Private Key Password + Contraseña de clave privada + + + + User Certificate + Certificado del usuario + + + + Private Key + Llave Privada + + + + CA Certificate + Certificado CA + + + + Connectivity + Conectividad + + + + Use STUN + Utilizar STUN + + + + STUN Address + Dirección STUN + + + + Use UPnP + Usar UPnP + + + + Use TURN + Usar TURN + + + + TURN Password + Contraseña TURN + + + + TURN Username + Nombre de usuario TURN + + + + TURN Address + Dirección TURN + + + + Media + Medios + + + + Enable Video + Habilitar vídeo + + + + Audio Codecs + Codecs de audio + + + + Video Codecs + Codecs de vídeo + + + + Audio Files (*.wav *.ogg *.opus *.mp3 *aiff *wma) + Ficheros de audio (*.wav *.ogg *.opus *.mp3 *aiff *wma) + + + + AnimatedOverlay + + + Form + Formulario + + + + BannedItemWidget + + + Form + Formulario + + + + name + Nombre + + + + id + ID + + + + CallWidget + + + Show conversations + Mostrar conversaciones + + + + Conversations + Conversaciones + + + + Search contact text input + Entrada de texto para buscar contacto + + + + Jami is free software for universal communication which respects the freedoms and privacy of its users. + Jami es software libre para la comunicación universal que respeta las libertades y la privacidad de sus usuarios. + + + + + This is your ID. +Copy and share it with your friends! + + +Este es tu ID. +¡Cópiala y compártela con tus amigos! + + + + Show ring ID QR code + Mostrar la Ring ID como código QR + + + + Share ring ID button + Botón de compartir el ID de Ring + + + + Double-click to copy + Doble click para copiar + + + + Error while generating QR Code + Hubo un error al generar el código QR + + + + + best name + mejor nombre + + + + best Id + mejor Id + + + + Back to homepage button + Botón para regresar a la página principal + + + + Add to contacts + Añadir a contactos + + + + Show invites + Mostrar invitaciones + + + + Invites + Invitaciones + + + + + Find a new or existing contact + Encontrar un contacto nuevo o existente + + + + Wants to talk to you! + ¡Quiere charlar contigo! + + + + Answer incoming call button + Botón de respuesta llamada entrante + + + + Ignore incoming call button + Ignorar el botón de llamada entrante + + + + Answer + Contestar + + + + Ignore + Ignorar + + + + Cancel outgoing call + Cancelar llamada saliente + + + + Cancel + Cancelar + + + + Start video call + Iniciar videollamada + + + + Start audio call + Empezar llamada de audio + + + + Clear conversation + Limpiar conversación + + + + Remove contact + Eliminar contacto + + + + Block contact + Bloquear contacto + + + + Copy number + Copiar Número + + + + Search your received invitations + Buscar tus invitaciones recibidas + + + + Contact me on Jami + Contacta conmigo en Jami + + + + My Id is : + Mi Id. es : + + + + %1 + %1 is the contact username + %1 + + + + %1 + %1 is the contact unique identifier + %1 + + + + Call incoming from %1 + Llamada entrante de %1 + + + + DeleteAccountDialog + + + Account deletion + Eliminar cuenta + + + + Do you really want to delete the following account? + ¿Desea eliminar la siguiente cuenta? + + + + If this account hasn't been exported, or added to another device, it will be irrevocably lost. + Esta cuenta se perderá definitivamente si no ha sido exportada o añadida a otro dispositivo. + + + + Permanently delete account + Eliminar cuenta definitivamente + + + + Delete + Borrar + + + + Cancel account deletion + Cancelar la eliminación de la cuenta + + + + Cancel + Cancelar + + + + DeviceItemWidget + + + Form + Formulario + + + + Device Id + Identificador de dispositivo + + + + this device + este dispositivo + + + + InviteButtonsWidget + + + Accept + Aceptar + + + + Refuse + No aceptar + + + + Block + Bloquear + + + + LinkDeviceDialog + + + Dialog + Mensaje + + + + Enter your account password + Introduce la contraseña de tu cuenta + + + + Password + Contraseña + + + + Ok + Aceptar + + + + Cancel + Cancelar + + + + Exporting account + Exportando cuenta + + + + Your PIN is + Tu PIN es + + + + PIN + PIN + + + + This pin and the account password should be entered in your device within 10 minutes. + El pin y la contraseña de la cuenta debe ser introducida en tu dispositivo en menos de 10 minutos + + + + Close + Cerrar + + + + Link Another Device + Conectar otro dispositivo + + + + Incorrect password + Contraseña incorrecta + + + + Something went wrong. +Please try again later. + Algo falló. +Por favor inténtelo de nuevo más tarde. + + + + MainWindow + + + Settings + Configuración + + + + Exit + Salir + + + + About + Acerca de + + + + Jami + Jami + + + + NameRegistrationDialog + + + Set Registered Name + Configurar nombre registrado + + + + Enter your account password + Introduzca el password de su cuenta + + + + Password text input + Entrada de constraseña + + + + Password text entry + Entrada de texto para contraseña + + + + Password + Contraseña + + + + Register + Registrar + + + + Cancel + Cancelar + + + + Registering Name + Registrando nombre + + + + Something went wrong + Algo salió mal + + + + Close + Cerrar + + + + Incorrect password + Contraseña incorrecta + + + + Network error + Error en la red + + + + NewWizardWidget + + + Form + Formulario + + + + Welcome Label + Etiqueta de Bienvenida + + + + Welcome to + Bienvenido(a) a + + + + Welcome Logo + Logo de Bienvenida + + + + Create Jami account button + Botón para crear cuenta de Jami + + + + Push button for Jami account creation start trigger + Pulse el boton para activar el inicio de creación de la cuenta Jami + + + + Create a Jami account + Crear una cuenta en Jami + + + + Link device button + Botón de vincular dispositivo + + + + Push button for device linkage start trigger + Pulse el botón para comenzar a enlazar el dispositivo + + + + Link this device to an account + Conectar este dispositivo a una cuenta + + + + Create Jami SIP account button + Botón de crear cuenta Jami SIP + + + + Push button for Jami SIP account creation start trigger + Pulsa el botón de crear cuenta Jami SIP + + + + Create a SIP account + Crear una cuenta SIP + + + + Link this device to an existing account + Vincular este dispositivo con una cuenta existente + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Ubuntu'; font-size:14px; color:#555555;">To link this device to another account, you first </span><span style=" font-family:'Ubuntu'; font-size:14px; font-weight:600; color:#555555;">need to obtain a PIN</span><span style=" font-family:'Ubuntu'; font-size:14px; color:#555555;"> code. To generate the PIN code:</span></p> +<ol style="margin-top: 0px; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; -qt-list-indent: 1;"><li style=" font-family:'Ubuntu'; font-size:14px; color:#555555;" style=" margin-top:12px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:14px;">Go to the </span><span style=" font-size:14px; font-weight:600;">Account management setting</span><span style=" font-size:14px;"> of a previous device</span></li> +<li style=" font-family:'Ubuntu'; font-size:14px; color:#555555;" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:14px;">Choose the </span><span style=" font-size:14px; font-weight:600;">Jami account</span><span style=" font-size:14px;"> you want to use</span></li> +<li style=" font-family:'Ubuntu'; font-size:14px; color:#555555;" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:14px;">Go to the </span><span style=" font-size:14px; font-weight:600;">Devices</span><span style=" font-size:14px;"> tab</span></li> +<li style=" font-family:'Ubuntu'; font-size:14px; color:#555555;" style=" margin-top:0px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:14px;">Select </span><span style=" font-size:14px; font-weight:600;">Add a device</span></li></ol> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Ubuntu'; font-size:14px; color:#555555;">You will get the necessary PIN to complete this form. The PIN is only valid for </span><span style=" font-family:'Ubuntu'; font-size:14px; font-weight:600; color:#555555;">10 minutes</span><span style=" font-family:'Ubuntu'; font-size:10px; color:#555555;">.</span></p></body></html> + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Ubuntu'; font-size:14px; color:#555555;">Para vincular este dispositivo con otra cuenta, primero debes </span><span style=" font-family:'Ubuntu'; font-size:14px; font-weight:600; color:#555555;">obtener un código</span><span style=" font-family:'Ubuntu'; font-size:14px; color:#555555;"> PIN. Para generar el código PIN:</span></p> +<ol style="margin-top: 0px; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; -qt-list-indent: 1;"><li style=" font-family:'Ubuntu'; font-size:14px; color:#555555;" style=" margin-top:12px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:14px;">Ve a las </span><span style=" font-size:14px; font-weight:600;">opciones de administración de la cuenta</span><span style=" font-size:14px;"> de un dispositivo previo</span></li> +<li style=" font-family:'Ubuntu'; font-size:14px; color:#555555;" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:14px;">Elije la </span><span style=" font-size:14px; font-weight:600;">cuenta Jami</span><span style=" font-size:14px;"> que deseas utilizar</span></li> +<li style=" font-family:'Ubuntu'; font-size:14px; color:#555555;" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:14px;">Ve a </span><span style=" font-size:14px; font-weight:600;">Dispositivos</span><span style=" font-size:14px;"> en las pestañas</span></li> +<li style=" font-family:'Ubuntu'; font-size:14px; color:#555555;" style=" margin-top:0px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:14px;">Selecciona </span><span style=" font-size:14px; font-weight:600;">Añadir un dispositivo</span></li></ol> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Ubuntu'; font-size:14px; color:#555555;">Recibirás el PIN necesario para completar este formulario. El PIN solo es válido durante </span><span style=" font-family:'Ubuntu'; font-size:14px; font-weight:600; color:#555555;">10 minutos</span><span style=" font-family:'Ubuntu'; font-size:10px; color:#555555;">.</span></p></body></html> + + + + Enter your pin: + Escribe tu PIN: + + + + Or import a file: + o importar a un fichero: + + + + Link from exported account archive file + Enlace desde archivo de cuenta exportado + + + + + + (None) + (Nada) + + + + Password: + Contraseña: + + + + + Profile + Perfil + + + + + Profile name + Nombre de perfil + + + + Account + Cuenta + + + + Register your username. +This will reserve the username so that only you can use it. +Your friends will be able to call you with your usename +instead of using your ID. + Registre su nombre de usuario. +Esto reservará el nombre de usuario de modo que sólo usted pueda usarlo. +Sus amigos podrán llamarlo por su nombre de usuario +en lugar de usar su ID. + + + + Public username checkbox + Casilla de verificación de nombre de usuario público + + + + Checkbox selecting if the user wants a public username + Marque la casilla de verificación si el usuario desea un nombre de usuario público + + + + Register public username + Registrar nombre de usuario público + + + + Public username edit + Editar nombre de usuario público + + + + Choose your username + Elije un nombre de usuario para ti + + + + Password text input + Entrada de constraseña + + + + Password text entry + Entrada de texto para contraseña + + + + + Password + Contraseña + + + + + Password confirmation text input + Confirmación de contraseña de entrada de texto + + + + Confirm password + Confirmar contraseña + + + + SIP Account + Cuenta SIP + + + + SIP Server edit + Edición de servidor SIP + + + + Server + Servidor + + + + SIP proxy input + Entrada de proxy SIP + + + + SIP proxy text entry + Entreda de texto del proxy SIP + + + + Proxy + Proxy + + + + SIP username input + Entrada de nombre de usuario SIP + + + + SIP Password text entry + Entrada de texto de la Contraseña SIP + + + + Username + Nombre de usuario + + + + + SIP Password text input + Entrada de texto de la Contraseña SIP + + + + Generating your Jami account… + Generando tu cuenta Jami... + + + + Previous page button + Botón de página anterior + + + + push button to access previous page of wizard + pulse el botón para acceder a la página anterior del asistente + + + + Previous + Anterior + + + + Cancel account create/link + Cancelar creación/enlace de cuenta + + + + push button to cancel account creation or linking + presione el botón para cancelar la creación o enlace de cuenta + + + + Back + Volver + + + + Next page Button + Botón de página siguiente + + + + Push button to access next page of wizard + Pulse el botón para acceder a la siguiente página del asistente + + + + Next + Siguiente + + + + Open File + Abrir fichero + + + + Jami archive files (*.gz); All files (*) + Ficheros de archivo de Jami (*.gz); Todos los ficheros (*) + + + + Your account needs to be migrated. Enter your password. + Debe migrar su cuenta. Introduzca su contraseña. + + + + Migrating your Jami account... + Migrando su cuenta de Jami... + + + + Importing account archive... + Importando archivo de cuenta... + + + + Generating your Jami account... + Generando tu cuenta de Jami... + + + + Generating your SIP account... + Creando tu cuenta SIP... + + + + Error creating account + Error al crear la cuenta + + + + PasswordDialog + + + Change Account Password + Cambiar contraseña de cuenta + + + + Enter Current Password + Ingrese la contraseña actual + + + + Enter New Password + Ingrese la nueva contraseña + + + + Confirm New Password + Confirme la nueva contraseña + + + + Confirm + Confirmar + + + + Cancel + Cancelar + + + + Current Password Incorrect + Contraseña actual incorrecta + + + + PhotoBoothDialog + + + Photobooth + Cabina de fotos + + + + PhotoboothWidget + + + Form + Formulario + + + + Photobooth display + Pantalla de Photobooth + + + + Choose File + Examinar + + + + Image Files (*.jpg *.jpeg *.png) + Ficheros de imagen (*.jpg *.jpeg *.png) + + + + PrivateBridging + + + Choose File + Examinar + + + + Files (*) + Ficheros (*) + + + + QObject + + + No default mail client found + No se encuentra el cliente de e-mail predeterminado + + + + + Edit Device Name + Editar nombre del dispositivo + + + + Unlink Device From Account + Desvincular dispositivo de la cuenta + + + + Save new device name + Guardar nuevo nombre de dispositivo + + + + Add as contact + Añadir como contacto + + + + RingButton + + + Select folder + Seleccionar carpeta + + + + SettingsWidget + + + Form + Formulario + + + + Settings + Configuración + + + + Account + Cuenta + + + + + General + General + + + + + Audio / Video + Audio / Vídeo + + + + System + Sistema + + + + Enable desktop notifications + Habilitar notificaciones de escritorio + + + + Keep minimized on close + Mantener minimizado al cerrar + + + + Download folder + Descargar carpeta + + + + Save in + guardar + + + + Always Recording + Siempre grabando + + + + Updates + Actualizaciones + + + + Check for updates automatically every + Buscar actualizaciones automáticamente cada + + + + Interval between update checks in days selector + Selector de intervalo de días entre chequeos de actualizaciones + + + + days + días + + + + Check for updates now button + Botón de búsqueda de inmediata actualizaciones + + + + Check for updates now + Buscar actualizaciones ahora + + + + Password + Contraseña + + + + + Enable + Activar + + + + toggle enable notifications + Cambiar Activar notificaciones + + + + Toggle keep minimized on close + Cambiar Mantener minimizado al cerrar + + + + Call Recordings + Grabación de llamadas + + + + Toggle automatic updates + Activar actualizaciones automáticas + + + + Jami Account + Cuenta Jami + + + + + Profile + Perfil + + + + + Identity + Identidad + + + + Id + ID + + + + Registered name + Nombre registrado + + + + Type here to register a username + Escriba aquí para registrar un nombre de usuario + + + + Register + Registrar + + + + Change Password + Cambiar contraseña + + + + Export Account + Exportar cuenta + + + + + Delete Account + Borrar cuenta + + + + Linked Devices + Dispositivos conectados + + + + Link Another Device + Conectar otro dispositivo + + + + Banned Contacts + Contactos bloqueados + + + + Format + Formato + + + + Video device framerate selector + Selector de velocidad de cuadros del vídeo + + + + Preview unavailable + Previsualización no disponible + + + + + Advanced Account Settings + Configuraciones de cuenta avanzadas + + + + SIP Account + Cuenta SIP + + + + Username + Nombre de usuario + + + + Hostname + Nombre del servidor + + + + Proxy + Proxy + + + + Audio + Audio + + + + Microphone + Micrófono + + + + Audio input device selector + Selector de dispositivo de entrada de audio + + + + Output Device + Dispositivo de salida + + + + Choose the output device + Selecciones el dispositivo de salida + + + + Video + Vídeo + + + + Device + Dispositivo + + + + Video device selector + Selector de dispositivo de video + + + + A registered name should not have any spaces and must be at least three letters long + Un nombre registrado no puede tener espacios y debe tener como mínimo tres letras + + + + This name is already taken + Este nombre ya está tomado + + + + + Enter an alias + Introducir un alias + + + + Register this name + Registrar este nombre + + + + Remove Device + Quitar dispositivo + + + + Enter this account's password to confirm the removal of this device + Ingrese la contraseña de esta cuenta para confirmar la quita de este dispositivo + + + + Are you sure you wish to remove this device? + ¿Está seguro de querer eliminar este dispositivo? + + + + Export Account Here + Exportar cuenta aquí + + + + Select A Folder For Your Downloads + Elija una carpeta para sus descargas + + + + Select A Folder For Your Recordings + Elija una carpeta para sus grabaciones + + + + VideoOverlay + + + Call on Hold + Llamada en espera + + + + Hold / Unhold + En espera / Reanudar + + + + Chat + Chat + + + + Mute Mic + Silenciar micrófono + + + + Record call + Grabar llamada + + + + Name label + Etiqueta de nombre + + + + Time elapsed + Tiempo transcurrido + + + + 00:00 + 00:00 + + + + Hangup + Cortar + + + + Mute Video + Silenciar Video + + + + VideoView + + + Share entire screen + Compartir toda la pantalla + + + + Share screen area + Compartir la ventana + + + + Share file + Compartir archivo + + + \ No newline at end of file diff --git a/translations/ring_client_windows_es_AR.ts b/translations/ring_client_windows_es_AR.ts new file mode 100644 index 00000000..9679572f --- /dev/null +++ b/translations/ring_client_windows_es_AR.ts @@ -0,0 +1,1605 @@ + + + AboutDialog + + + + About + Acerca de + + + + about button + Botón Acerca de + + + + credits button + Botón Créditos + + + + Credits + Créditos + + + + Free as in Freedom + Libre como en libertad + + + + The Microsoft Windows client for Jami. +Jami is a secured and distributed communication software. + El cliente de Jami para Microsoft Windows. +Jami es un software de comunicación seguro y distribuido. + + + + version + versión + + + + Created by: + Creado por: + + + + Artwork by: + Ilustraciones realizadas por: + + + + Based on the SFLPhone project + Basado en el projecto SFLPhone + + + + AccountItemDelegate + + + Add Account + Añadir cuenta + + + + AdvancedSIPSettingsWidget + + + Form + Formulario + + + + Call Settings + Opciones de llamada + + + + Auto Answer Calls + Responder automáticamente + + + + Enable Custom Ringtone + Habilitar tono de llamada personalizado + + + + Connectivity + Conectividad + + + + STUN Address + Dirección STUN + + + + Use STUN + Usar STUN + + + + Use UPnP + Usar UPnP + + + + Use TURN + Usar TURN + + + + TURN Password + Contraseña TURN + + + + TURN Username + Usuario TURN + + + + TURN Address + Dirección TURN + + + + Media + Medios + + + + Enable Video + Permitir video + + + + Video Codecs + Códecs de video + + + + Audio Codecs + Códecs de audio + + + + Audio Files (*.wav *.ogg *.opus *.mp3 *aiff *wma) + Archivos de audio (*.wav *.ogg *.opus *.mp3 *aiff *wma) + + + + Add a custom ringtone + Agregar un tono de llamada personalizado + + + + AdvancedSettingsWidget + + + Form + Formulario + + + + Call Settings + Opciones de llamada + + + + Allow Calls From Untrusted Peers + Permitir llamadas de contactos no conocidos + + + + Auto Answer Calls + Responder automáticamente + + + + Enable Custom Ringtone + Habilitar tono de llamada personalizado + + + + Add a custom ringtone + Agregar un tono de llamada personalizado + + + + Name Server + Nombre del servidor + + + + Address + Dirección + + + + OpenDHT Configuration + Configuración de OpenDHT + + + + Enable Proxy + Habilitar Proxy + + + + Bootstrap + Bootstrap + + + + Security + Seguridad + + + + Private Key Password + Contraseña de clave privada + + + + User Certificate + Certificado de Usuario + + + + Private Key + Clave privada + + + + CA Certificate + Certificado CA + + + + Connectivity + Conectividad + + + + Use STUN + Usar STUN + + + + STUN Address + Dirección STUN + + + + Use UPnP + Usar UPnP + + + + Use TURN + Usar TURN + + + + TURN Password + Contraseña TURN + + + + TURN Username + Usuario TURN + + + + TURN Address + Dirección TURN + + + + Media + Medios + + + + Enable Video + Permitir video + + + + Audio Codecs + Códecs de audio + + + + Video Codecs + Códecs de video + + + + Audio Files (*.wav *.ogg *.opus *.mp3 *aiff *wma) + Archivos de audio (*.wav *.ogg *.opus *.mp3 *aiff *wma) + + + + AnimatedOverlay + + + Form + Formulario + + + + BannedItemWidget + + + Form + Formulario + + + + name + nombre + + + + id + ID + + + + CallWidget + + + Show conversations + Mostrar conversaciones + + + + Conversations + Conversaciones + + + + Search contact text input + Entrada de texto para buscar contacto + + + + Jami is free software for universal communication which respects the freedoms and privacy of its users. + Jami es un software libre para comunicarse universalmente que respeta las libertades y la privacidad de sus usuarios. + + + + + This is your ID. +Copy and share it with your friends! + + +Este es su ID. +¡Cópielo y compártalo con sus amigos! + + + + Show ring ID QR code + Mostrar el ID de Ring como código QR + + + + Share ring ID button + Botón compartir el ID de Ring + + + + Double-click to copy + Doble click para copiar + + + + Error while generating QR Code + Error al generar el Código QR + + + + + best name + mejor nombre + + + + best Id + mejor ID + + + + Back to homepage button + Volver a la página de inicio + + + + Add to contacts + Agregar a contactos + + + + Show invites + Mostrar invitaciones + + + + Invites + Invitaciones + + + + + Find a new or existing contact + Buscar un contacto nuevo o existente + + + + Wants to talk to you! + ¡Quiere hablarte! + + + + Answer incoming call button + Botón responder llamada entrante + + + + Ignore incoming call button + Botón ignorar llamada entrante + + + + Answer + Respuesta + + + + Ignore + Ignorar + + + + Cancel outgoing call + Cancelar llamada saliente + + + + Cancel + Cancelar + + + + Start video call + Iniciar una videollamada + + + + Start audio call + Iniciar una llamada de voz + + + + Clear conversation + Limpiar conversación + + + + Remove contact + Eliminar contacto + + + + Block contact + Bloquear contacto + + + + Copy number + Copiar número + + + + Search your received invitations + Buscar tus invitaciones recibidas + + + + Contact me on Jami + Contactá conmigo en Jami + + + + My Id is : + Mi ID es: + + + + %1 + %1 is the contact username + %1 + + + + %1 + %1 is the contact unique identifier + %1 + + + + Call incoming from %1 + Llamada entrante de %1 + + + + DeleteAccountDialog + + + Account deletion + Eliminación de cuenta + + + + Do you really want to delete the following account? + ¿Realmente quiere eliminar la cuenta? + + + + If this account hasn't been exported, or added to another device, it will be irrevocably lost. + Si esta cuenta no ha sido exportada, o añadida a otro dispositivo, se perderá definitivamente. + + + + Permanently delete account + Eliminar cuenta permanentemente + + + + Delete + Eliminar + + + + Cancel account deletion + Cancelar la eliminación de cuenta + + + + Cancel + Cancelar + + + + DeviceItemWidget + + + Form + Formulario + + + + Device Id + ID del dispositivo + + + + this device + este dispositivo + + + + InviteButtonsWidget + + + Accept + Aceptar + + + + Refuse + Rechazar + + + + Block + Bloquear + + + + LinkDeviceDialog + + + Dialog + Diálogo + + + + Enter your account password + Ingrese la contraseña de la cuenta + + + + Password + Contraseña + + + + Ok + Ok + + + + Cancel + Cancelar + + + + Exporting account + Exportando cuenta + + + + Your PIN is + Tu PIN es: + + + + PIN + PIN + + + + This pin and the account password should be entered in your device within 10 minutes. + Este PIN y la contraseña de la contraseña deben ser ingresadas en tu dispositivo en los próximos 10 minutos. + + + + Close + Cerrar + + + + Link Another Device + Vincular otro dispositivo + + + + Incorrect password + Contraseña incorrecta + + + + Something went wrong. +Please try again later. + Algo salió mal. +Por favor intente de nuevo más tarde. + + + + MainWindow + + + Settings + Ajustes + + + + Exit + Salir + + + + About + Acerca de + + + + Jami + Jami + + + + NameRegistrationDialog + + + Set Registered Name + Establecer nombre registrado + + + + Enter your account password + Ingrese la contraseña de la cuenta + + + + Password text input + Entrada de contraseña + + + + Password text entry + Entrada de texto de contraseña + + + + Password + Contraseña + + + + Register + Registrar + + + + Cancel + Cancelar + + + + Registering Name + Registrando nombre + + + + Something went wrong + Algo salió mal + + + + Close + Cerrar + + + + Incorrect password + Contraseña incorrecta + + + + Network error + Error de red + + + + NewWizardWidget + + + Form + Formulario + + + + Welcome Label + Etiqueta de bienvenida + + + + Welcome to + Bienvenido a + + + + Welcome Logo + Logo de bienvenida + + + + Create Jami account button + Botón crear una cuenta de Jami + + + + Push button for Jami account creation start trigger + Pulse el boton para activar el inicio de creación de la cuenta Jami + + + + Create a Jami account + Crear una cuenta de Jami + + + + Link device button + Botón vincular dispositivo + + + + Push button for device linkage start trigger + Pulse el botón para comenzar a enlazar el dispositivo + + + + Link this device to an account + Vincular este dispositivo a una cuenta + + + + Create Jami SIP account button + Botón crear cuenta Jami SIP + + + + Push button for Jami SIP account creation start trigger + Pulse el botón crear cuenta Jami SIP + + + + Create a SIP account + Crear una cuenta SIP + + + + Link this device to an existing account + Enlazar este dispositivo a una cuenta existente + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Ubuntu'; font-size:14px; color:#555555;">To link this device to another account, you first </span><span style=" font-family:'Ubuntu'; font-size:14px; font-weight:600; color:#555555;">need to obtain a PIN</span><span style=" font-family:'Ubuntu'; font-size:14px; color:#555555;"> code. To generate the PIN code:</span></p> +<ol style="margin-top: 0px; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; -qt-list-indent: 1;"><li style=" font-family:'Ubuntu'; font-size:14px; color:#555555;" style=" margin-top:12px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:14px;">Go to the </span><span style=" font-size:14px; font-weight:600;">Account management setting</span><span style=" font-size:14px;"> of a previous device</span></li> +<li style=" font-family:'Ubuntu'; font-size:14px; color:#555555;" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:14px;">Choose the </span><span style=" font-size:14px; font-weight:600;">Jami account</span><span style=" font-size:14px;"> you want to use</span></li> +<li style=" font-family:'Ubuntu'; font-size:14px; color:#555555;" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:14px;">Go to the </span><span style=" font-size:14px; font-weight:600;">Devices</span><span style=" font-size:14px;"> tab</span></li> +<li style=" font-family:'Ubuntu'; font-size:14px; color:#555555;" style=" margin-top:0px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:14px;">Select </span><span style=" font-size:14px; font-weight:600;">Add a device</span></li></ol> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Ubuntu'; font-size:14px; color:#555555;">You will get the necessary PIN to complete this form. The PIN is only valid for </span><span style=" font-family:'Ubuntu'; font-size:14px; font-weight:600; color:#555555;">10 minutes</span><span style=" font-family:'Ubuntu'; font-size:10px; color:#555555;">.</span></p></body></html> + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Cantarell'; font-size:11pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Ubuntu'; font-size:12pt;">Para enlazar este dispositivo a otra cuenta, primero </span><span style=" font-family:'Ubuntu'; font-size:12pt; font-weight:600;">necesita obtener un código</span><span style=" font-family:'Ubuntu'; font-size:12pt;"> PIN. Para generar el código PIN:</span></p> +<ol style="margin-top: 0px; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; -qt-list-indent: 1;"><li style=" font-family:'Ubuntu'; font-size:12pt;" style=" margin-top:12px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Diríjase a los <span style=" font-weight:600;">Ajustes de administración de cuenta</span> de un dispositivo previo</li> +<li style=" font-family:'Ubuntu'; font-size:12pt;" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Elija la <span style=" font-weight:600;">cuenta Jami</span> que quiera usar</li> +<li style=" font-family:'Ubuntu'; font-size:12pt;" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Vaya a la pestaña </li><span style=" font-weight:600;">Dispositivos</span> +<li style=" font-family:'Ubuntu'; font-size:12pt;" style=" margin-top:0px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Seleccione <span style=" font-weight:600;">Añadir un dispositivo</span></li></ol> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Ubuntu'; font-size:12pt;">Obtendrá el PIN necesario para completar este formulario. El PIN sólo es valido por </span><span style=" font-family:'Ubuntu'; font-size:12pt; font-weight:600;">10 minutos</span><span style=" font-family:'Ubuntu'; font-size:12pt;">.</span></p></body></html> + + + + Enter your pin: + Ingrese su pin: + + + + Or import a file: + O importar un archivo: + + + + Link from exported account archive file + Enlace desde archivo de cuenta exportado + + + + + + (None) + (Ninguno) + + + + Password: + Contraseña: + + + + + Profile + Perfil + + + + + Profile name + Nombre de perfil + + + + Account + Cuenta + + + + Register your username. +This will reserve the username so that only you can use it. +Your friends will be able to call you with your usename +instead of using your ID. + Registre su nombre de usuario. +Esto reservará el nombre de usuario de modo que sólo usted pueda usarlo. +Sus amigos podrán llamarlo por su nombre de usuario +en lugar de usar su ID. + + + + Public username checkbox + Casilla de verificación de nombre de usuario público + + + + Checkbox selecting if the user wants a public username + Marque la casilla de verificación si el usuario desea un nombre de usuario público + + + + Register public username + Registrar nombre de usuario público + + + + Public username edit + Editar nombre de usuario público + + + + Choose your username + Elija su nombre de usuario + + + + Password text input + Entrada de texto de contraseña + + + + Password text entry + Entrada de texto de contraseña + + + + + Password + Contraseña + + + + + Password confirmation text input + Confirmación de contraseña de entrada de texto + + + + Confirm password + Confirmar contraseña + + + + SIP Account + Cuenta SIP + + + + SIP Server edit + Editar servidor SIP + + + + Server + Servidor + + + + SIP proxy input + Entrada de proxy SIP + + + + SIP proxy text entry + Entrada de texto de SIP proxy + + + + Proxy + Proxy + + + + SIP username input + Entrada de nombre de usuario SIP + + + + SIP Password text entry + Entrada de texto de contraseña SIP + + + + Username + Nombre de usuario + + + + + SIP Password text input + Entrada de texto de contraseña SIP + + + + Generating your Jami account… + Generando su cuenta Jami... + + + + Previous page button + Botón página anterior + + + + push button to access previous page of wizard + pulse el botón para acceder a la página anterior del asistente + + + + Previous + Anterior + + + + Cancel account create/link + Cancelar la creación/vinculación de cuenta + + + + push button to cancel account creation or linking + pulse el botón para cancelar la creación o vinculación de cuenta + + + + Back + Atrás + + + + Next page Button + Botón página siguiente + + + + Push button to access next page of wizard + Pulse el botón para acceder a la página siguiente del asistente + + + + Next + Siguiente + + + + Open File + Abrir Archivo + + + + Jami archive files (*.gz); All files (*) + Archivos de Jami (*.gz); Todos los ficheros (*) + + + + Your account needs to be migrated. Enter your password. + Su cuenta debe ser migrada. Ingrese su contraseña. + + + + Migrating your Jami account... + MIgrando su cuenta Jami... + + + + Importing account archive... + Importando su cuenta archivada... + + + + Generating your Jami account... + Generando su cuenta Jami... + + + + Generating your SIP account... + Generando su cuenta SIP... + + + + Error creating account + Error en la creación de cuenta + + + + PasswordDialog + + + Change Account Password + Cambiar la contraseña de la cuenta + + + + Enter Current Password + Ingresar la contraseña actual + + + + Enter New Password + Ingresar la nueva contraseña + + + + Confirm New Password + Confirmar la nueva contraseña + + + + Confirm + Confirmar + + + + Cancel + Cancelar + + + + Current Password Incorrect + Contraseña actual incorrecta + + + + PhotoBoothDialog + + + Photobooth + Cabina de fotos + + + + PhotoboothWidget + + + Form + Formulario + + + + Photobooth display + Pantalla de cabina de fotos + + + + Choose File + Elegir archivo + + + + Image Files (*.jpg *.jpeg *.png) + Archivos de imágenes (*.jpg *.jpeg *.png) + + + + PrivateBridging + + + Choose File + Elegir archivo + + + + Files (*) + Archivos (*) + + + + QObject + + + No default mail client found + No se encontró el cliente de e-mail predeterminado + + + + + Edit Device Name + Editar nombre de dispositivo + + + + Unlink Device From Account + Desvincular dispositivo de la cuenta + + + + Save new device name + Guardar nmbre de nuevo dispositivo + + + + Add as contact + Agregar como contacto + + + + RingButton + + + Select folder + Seleccionar carpeta + + + + SettingsWidget + + + Form + Formulario + + + + Settings + Ajustes + + + + Account + Cuenta + + + + + General + General + + + + + Audio / Video + Audio / Video + + + + System + Sistema + + + + Enable desktop notifications + Habilitar notificaciones en el escritorio + + + + Keep minimized on close + Mantener minimizado al cerrar + + + + Download folder + Descargar carpeta + + + + Save in + Guardar en + + + + Always Recording + Siempre grabando + + + + Updates + Actualizaciones + + + + Check for updates automatically every + Comprobar actualizaciones automáticamente cada + + + + Interval between update checks in days selector + Selector de intervalo de días entre comprobación de actualizaciones + + + + days + días + + + + Check for updates now button + Botón comprobar actualizaciones en forma inmediata + + + + Check for updates now + Comprobar actualizaciones ahora + + + + Password + Contraseña + + + + + Enable + Habilitar + + + + toggle enable notifications + Cambiar Activar notificaciones + + + + Toggle keep minimized on close + Cambiar Mantener minimizado al cerrar + + + + Call Recordings + Grabaciones de llamadas + + + + Toggle automatic updates + Activar actualizaciones automáticas + + + + Jami Account + Cuenta Jami + + + + + Profile + Perfil + + + + + Identity + Identidad + + + + Id + ID + + + + Registered name + Nombre registrado + + + + Type here to register a username + Escriba aquí para registrar un nombre de usuario + + + + Register + Registrar + + + + Change Password + Cambiar contraseña + + + + Export Account + Exportar cuenta + + + + + Delete Account + Eliminar cuenta + + + + Linked Devices + Dispositvos vinculados + + + + Link Another Device + Vincular otro dispositivo + + + + Banned Contacts + Contactos bloqueados + + + + Format + Formato + + + + Video device framerate selector + Selector de velocidad de cuadros del dispositivo de video + + + + Preview unavailable + Vista previa no disponible + + + + + Advanced Account Settings + Opciones avanzadas de cuenta + + + + SIP Account + Cuenta SIP + + + + Username + Nombre de usuario + + + + Hostname + Nombre del anfitrión + + + + Proxy + Proxy + + + + Audio + Audio + + + + Microphone + Micrófono + + + + Audio input device selector + Selector de dispositivo de entrada de audio + + + + Output Device + Dispositivo de Salida + + + + Choose the output device + Elija el dispositivo de salida + + + + Video + Video + + + + Device + Dispositivo + + + + Video device selector + Selector de dispositivo de video + + + + A registered name should not have any spaces and must be at least three letters long + Un nombre de registro no debe tener espacios y debe tener al menos tres letras como mínimo de extensión + + + + This name is already taken + Este nombre ya está en uso + + + + + Enter an alias + Ingresar un alias + + + + Register this name + Registrar este nombre + + + + Remove Device + Remover dispositivo + + + + Enter this account's password to confirm the removal of this device + Ingrese la contraseña de la cuenta para confirmar la remoción del dispositivo + + + + Are you sure you wish to remove this device? + ¿Está seguro que desea remover este dispositivo? + + + + Export Account Here + Exportar cuenta aquí + + + + Select A Folder For Your Downloads + Seleccione una carpeta para sus descargas + + + + Select A Folder For Your Recordings + Seleccione una carpeta para sus grabaciones + + + + VideoOverlay + + + Call on Hold + Llamada en espera + + + + Hold / Unhold + En espera / Reanudar + + + + Chat + Chat + + + + Mute Mic + Silenciar micrófono + + + + Record call + Grabar llamada + + + + Name label + Etiqueta de nombre + + + + Time elapsed + Tiempo transcurrido + + + + 00:00 + 00:00 + + + + Hangup + Colgar + + + + Mute Video + Deshabilitar video + + + + VideoView + + + Share entire screen + Compartir pantalla completa + + + + Share screen area + Compartir área de pantalla específica + + + + Share file + Compartir archivo + + + \ No newline at end of file diff --git a/translations/ring_client_windows_es_MX.ts b/translations/ring_client_windows_es_MX.ts new file mode 100644 index 00000000..68701a02 --- /dev/null +++ b/translations/ring_client_windows_es_MX.ts @@ -0,0 +1,1589 @@ + + + AboutDialog + + + + About + + + + + about button + + + + + credits button + + + + + Credits + + + + + Free as in Freedom + + + + + The Microsoft Windows client for Jami. +Jami is a secured and distributed communication software. + + + + + version + + + + + Created by: + + + + + Artwork by: + + + + + Based on the SFLPhone project + + + + + AccountItemDelegate + + + Add Account + + + + + AdvancedSIPSettingsWidget + + + Form + + + + + Call Settings + + + + + Auto Answer Calls + + + + + Enable Custom Ringtone + + + + + Connectivity + + + + + STUN Address + + + + + Use STUN + + + + + Use UPnP + + + + + Use TURN + + + + + TURN Password + + + + + TURN Username + + + + + TURN Address + + + + + Media + + + + + Enable Video + + + + + Video Codecs + + + + + Audio Codecs + + + + + Audio Files (*.wav *.ogg *.opus *.mp3 *aiff *wma) + + + + + Add a custom ringtone + + + + + AdvancedSettingsWidget + + + Form + + + + + Call Settings + + + + + Allow Calls From Untrusted Peers + + + + + Auto Answer Calls + + + + + Enable Custom Ringtone + + + + + Add a custom ringtone + + + + + Name Server + + + + + Address + + + + + OpenDHT Configuration + + + + + Enable Proxy + + + + + Bootstrap + + + + + Security + + + + + Private Key Password + + + + + User Certificate + + + + + Private Key + + + + + CA Certificate + + + + + Connectivity + + + + + Use STUN + + + + + STUN Address + + + + + Use UPnP + + + + + Use TURN + + + + + TURN Password + + + + + TURN Username + + + + + TURN Address + + + + + Media + + + + + Enable Video + + + + + Audio Codecs + + + + + Video Codecs + + + + + Audio Files (*.wav *.ogg *.opus *.mp3 *aiff *wma) + + + + + AnimatedOverlay + + + Form + + + + + BannedItemWidget + + + Form + + + + + name + + + + + id + + + + + CallWidget + + + Show conversations + + + + + Conversations + Conversaciones + + + + Search contact text input + + + + + Jami is free software for universal communication which respects the freedoms and privacy of its users. + + + + + + This is your ID. +Copy and share it with your friends! + + + + + + Show ring ID QR code + + + + + Share ring ID button + + + + + Double-click to copy + + + + + Error while generating QR Code + + + + + + best name + + + + + best Id + + + + + Back to homepage button + + + + + Add to contacts + + + + + Show invites + + + + + Invites + + + + + + Find a new or existing contact + + + + + Wants to talk to you! + + + + + Answer incoming call button + + + + + Ignore incoming call button + + + + + Answer + + + + + Ignore + + + + + Cancel outgoing call + + + + + Cancel + Cancelar + + + + Start video call + + + + + Start audio call + + + + + Clear conversation + + + + + Remove contact + + + + + Block contact + + + + + Copy number + + + + + Search your received invitations + + + + + Contact me on Jami + + + + + My Id is : + + + + + %1 + %1 is the contact username + + + + + %1 + %1 is the contact unique identifier + + + + + Call incoming from %1 + + + + + DeleteAccountDialog + + + Account deletion + + + + + Do you really want to delete the following account? + + + + + If this account hasn't been exported, or added to another device, it will be irrevocably lost. + + + + + Permanently delete account + + + + + Delete + + + + + Cancel account deletion + + + + + Cancel + Cancelar + + + + DeviceItemWidget + + + Form + + + + + Device Id + + + + + this device + + + + + InviteButtonsWidget + + + Accept + + + + + Refuse + + + + + Block + + + + + LinkDeviceDialog + + + Dialog + + + + + Enter your account password + + + + + Password + + + + + Ok + Ok + + + + Cancel + Cancelar + + + + Exporting account + + + + + Your PIN is + + + + + PIN + PIN + + + + This pin and the account password should be entered in your device within 10 minutes. + + + + + Close + + + + + Link Another Device + + + + + Incorrect password + + + + + Something went wrong. +Please try again later. + + + + + MainWindow + + + Settings + + + + + Exit + + + + + About + + + + + Jami + + + + + NameRegistrationDialog + + + Set Registered Name + + + + + Enter your account password + + + + + Password text input + + + + + Password text entry + + + + + Password + + + + + Register + + + + + Cancel + Cancelar + + + + Registering Name + + + + + Something went wrong + + + + + Close + + + + + Incorrect password + + + + + Network error + + + + + NewWizardWidget + + + Form + + + + + Welcome Label + + + + + Welcome to + + + + + Welcome Logo + + + + + Create Jami account button + + + + + Push button for Jami account creation start trigger + + + + + Create a Jami account + + + + + Link device button + + + + + Push button for device linkage start trigger + + + + + Link this device to an account + Vincular este dispositivo a una cuenta + + + + Create Jami SIP account button + + + + + Push button for Jami SIP account creation start trigger + + + + + Create a SIP account + + + + + Link this device to an existing account + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Ubuntu'; font-size:14px; color:#555555;">To link this device to another account, you first </span><span style=" font-family:'Ubuntu'; font-size:14px; font-weight:600; color:#555555;">need to obtain a PIN</span><span style=" font-family:'Ubuntu'; font-size:14px; color:#555555;"> code. To generate the PIN code:</span></p> +<ol style="margin-top: 0px; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; -qt-list-indent: 1;"><li style=" font-family:'Ubuntu'; font-size:14px; color:#555555;" style=" margin-top:12px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:14px;">Go to the </span><span style=" font-size:14px; font-weight:600;">Account management setting</span><span style=" font-size:14px;"> of a previous device</span></li> +<li style=" font-family:'Ubuntu'; font-size:14px; color:#555555;" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:14px;">Choose the </span><span style=" font-size:14px; font-weight:600;">Jami account</span><span style=" font-size:14px;"> you want to use</span></li> +<li style=" font-family:'Ubuntu'; font-size:14px; color:#555555;" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:14px;">Go to the </span><span style=" font-size:14px; font-weight:600;">Devices</span><span style=" font-size:14px;"> tab</span></li> +<li style=" font-family:'Ubuntu'; font-size:14px; color:#555555;" style=" margin-top:0px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:14px;">Select </span><span style=" font-size:14px; font-weight:600;">Add a device</span></li></ol> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Ubuntu'; font-size:14px; color:#555555;">You will get the necessary PIN to complete this form. The PIN is only valid for </span><span style=" font-family:'Ubuntu'; font-size:14px; font-weight:600; color:#555555;">10 minutes</span><span style=" font-family:'Ubuntu'; font-size:10px; color:#555555;">.</span></p></body></html> + + + + + Enter your pin: + + + + + Or import a file: + + + + + Link from exported account archive file + + + + + + + (None) + + + + + Password: + + + + + + Profile + + + + + + Profile name + + + + + Account + Cuenta + + + + Register your username. +This will reserve the username so that only you can use it. +Your friends will be able to call you with your usename +instead of using your ID. + + + + + Public username checkbox + + + + + Checkbox selecting if the user wants a public username + + + + + Register public username + + + + + Public username edit + + + + + Choose your username + + + + + Password text input + + + + + Password text entry + + + + + + Password + + + + + + Password confirmation text input + + + + + Confirm password + + + + + SIP Account + + + + + SIP Server edit + + + + + Server + + + + + SIP proxy input + + + + + SIP proxy text entry + + + + + Proxy + + + + + SIP username input + + + + + SIP Password text entry + + + + + Username + + + + + + SIP Password text input + + + + + Generating your Jami account… + + + + + Previous page button + + + + + push button to access previous page of wizard + + + + + Previous + + + + + Cancel account create/link + + + + + push button to cancel account creation or linking + + + + + Back + + + + + Next page Button + + + + + Push button to access next page of wizard + + + + + Next + Siguiente + + + + Open File + + + + + Jami archive files (*.gz); All files (*) + + + + + Your account needs to be migrated. Enter your password. + + + + + Migrating your Jami account... + + + + + Importing account archive... + + + + + Generating your Jami account... + + + + + Generating your SIP account... + + + + + Error creating account + + + + + PasswordDialog + + + Change Account Password + + + + + Enter Current Password + + + + + Enter New Password + + + + + Confirm New Password + + + + + Confirm + + + + + Cancel + Cancelar + + + + Current Password Incorrect + + + + + PhotoBoothDialog + + + Photobooth + + + + + PhotoboothWidget + + + Form + + + + + Photobooth display + + + + + Choose File + + + + + Image Files (*.jpg *.jpeg *.png) + + + + + PrivateBridging + + + Choose File + + + + + Files (*) + + + + + QObject + + + No default mail client found + + + + + + Edit Device Name + + + + + Unlink Device From Account + + + + + Save new device name + + + + + Add as contact + + + + + RingButton + + + Select folder + + + + + SettingsWidget + + + Form + + + + + Settings + + + + + Account + Cuenta + + + + + General + + + + + + Audio / Video + + + + + System + + + + + Enable desktop notifications + + + + + Keep minimized on close + + + + + Download folder + + + + + Save in + + + + + Always Recording + + + + + Updates + + + + + Check for updates automatically every + + + + + Interval between update checks in days selector + + + + + days + + + + + Check for updates now button + + + + + Check for updates now + + + + + Password + + + + + + Enable + + + + + toggle enable notifications + + + + + Toggle keep minimized on close + + + + + Call Recordings + + + + + Toggle automatic updates + + + + + Jami Account + + + + + + Profile + + + + + + Identity + + + + + Id + + + + + Registered name + + + + + Type here to register a username + + + + + Register + + + + + Change Password + + + + + Export Account + + + + + + Delete Account + + + + + Linked Devices + + + + + Link Another Device + + + + + Banned Contacts + + + + + Format + + + + + Video device framerate selector + + + + + Preview unavailable + + + + + + Advanced Account Settings + + + + + SIP Account + + + + + Username + + + + + Hostname + + + + + Proxy + + + + + Audio + Audio + + + + Microphone + + + + + Audio input device selector + + + + + Output Device + + + + + Choose the output device + + + + + Video + Video + + + + Device + Dispositivo + + + + Video device selector + + + + + A registered name should not have any spaces and must be at least three letters long + + + + + This name is already taken + + + + + + Enter an alias + + + + + Register this name + + + + + Remove Device + + + + + Enter this account's password to confirm the removal of this device + + + + + Are you sure you wish to remove this device? + + + + + Export Account Here + + + + + Select A Folder For Your Downloads + + + + + Select A Folder For Your Recordings + + + + + VideoOverlay + + + Call on Hold + + + + + Hold / Unhold + + + + + Chat + + + + + Mute Mic + + + + + Record call + + + + + Name label + + + + + Time elapsed + + + + + 00:00 + + + + + Hangup + + + + + Mute Video + + + + + VideoView + + + Share entire screen + + + + + Share screen area + + + + + Share file + + + + \ No newline at end of file diff --git a/translations/ring_client_windows_et_EE.ts b/translations/ring_client_windows_et_EE.ts new file mode 100644 index 00000000..1b90f250 --- /dev/null +++ b/translations/ring_client_windows_et_EE.ts @@ -0,0 +1,1591 @@ + + + + + AboutDialog + + + + About + + + + + about button + + + + + credits button + + + + + Credits + + + + + Free as in Freedom + + + + + The Microsoft Windows client for Jami. +Jami is a secured and distributed communication software. + + + + + version + + + + + Created by: + + + + + Artwork by: + + + + + Based on the SFLPhone project + + + + + AccountItemDelegate + + + Add Account + + + + + AdvancedSIPSettingsWidget + + + Form + + + + + Call Settings + + + + + Auto Answer Calls + + + + + Enable Custom Ringtone + + + + + Connectivity + + + + + STUN Address + + + + + Use STUN + + + + + Use UPnP + + + + + Use TURN + + + + + TURN Password + + + + + TURN Username + + + + + TURN Address + + + + + Media + + + + + Enable Video + + + + + Video Codecs + + + + + Audio Codecs + + + + + Audio Files (*.wav *.ogg *.opus *.mp3 *aiff *wma) + + + + + Add a custom ringtone + + + + + AdvancedSettingsWidget + + + Form + + + + + Call Settings + + + + + Allow Calls From Untrusted Peers + + + + + Auto Answer Calls + + + + + Enable Custom Ringtone + + + + + Add a custom ringtone + + + + + Name Server + + + + + Address + + + + + OpenDHT Configuration + + + + + Enable Proxy + + + + + Bootstrap + + + + + Security + + + + + Private Key Password + + + + + User Certificate + + + + + Private Key + + + + + CA Certificate + + + + + Connectivity + + + + + Use STUN + + + + + STUN Address + + + + + Use UPnP + + + + + Use TURN + + + + + TURN Password + + + + + TURN Username + + + + + TURN Address + + + + + Media + + + + + Enable Video + + + + + Audio Codecs + + + + + Video Codecs + + + + + Audio Files (*.wav *.ogg *.opus *.mp3 *aiff *wma) + + + + + AnimatedOverlay + + + Form + + + + + BannedItemWidget + + + Form + + + + + name + + + + + id + + + + + CallWidget + + + Show conversations + + + + + Conversations + + + + + Search contact text input + + + + + Jami is free software for universal communication which respects the freedoms and privacy of its users. + + + + + + This is your ID. +Copy and share it with your friends! + + + + + + Show ring ID QR code + + + + + Share ring ID button + + + + + Double-click to copy + + + + + Error while generating QR Code + + + + + + best name + + + + + best Id + + + + + Back to homepage button + + + + + Add to contacts + + + + + Show invites + + + + + Invites + + + + + + Find a new or existing contact + + + + + Wants to talk to you! + + + + + Answer incoming call button + + + + + Ignore incoming call button + + + + + Answer + vasta + + + + Ignore + + + + + Cancel outgoing call + + + + + Cancel + + + + + Start video call + + + + + Start audio call + + + + + Clear conversation + + + + + Remove contact + + + + + Block contact + + + + + Copy number + + + + + Search your received invitations + + + + + Contact me on Jami + + + + + My Id is : + + + + + %1 + %1 is the contact username + + + + + %1 + %1 is the contact unique identifier + + + + + Call incoming from %1 + + + + + DeleteAccountDialog + + + Account deletion + + + + + Do you really want to delete the following account? + + + + + If this account hasn't been exported, or added to another device, it will be irrevocably lost. + + + + + Permanently delete account + + + + + Delete + + + + + Cancel account deletion + + + + + Cancel + + + + + DeviceItemWidget + + + Form + + + + + Device Id + + + + + this device + + + + + InviteButtonsWidget + + + Accept + + + + + Refuse + + + + + Block + + + + + LinkDeviceDialog + + + Dialog + + + + + Enter your account password + + + + + Password + + + + + Ok + + + + + Cancel + + + + + Exporting account + + + + + Your PIN is + + + + + PIN + + + + + This pin and the account password should be entered in your device within 10 minutes. + + + + + Close + + + + + Link Another Device + + + + + Incorrect password + + + + + Something went wrong. +Please try again later. + + + + + MainWindow + + + Settings + + + + + Exit + + + + + About + + + + + Jami + + + + + NameRegistrationDialog + + + Set Registered Name + + + + + Enter your account password + + + + + Password text input + + + + + Password text entry + + + + + Password + + + + + Register + + + + + Cancel + + + + + Registering Name + + + + + Something went wrong + + + + + Close + + + + + Incorrect password + + + + + Network error + + + + + NewWizardWidget + + + Form + + + + + Welcome Label + + + + + Welcome to + + + + + Welcome Logo + + + + + Create Jami account button + + + + + Push button for Jami account creation start trigger + + + + + Create a Jami account + + + + + Link device button + + + + + Push button for device linkage start trigger + + + + + Link this device to an account + + + + + Create Jami SIP account button + + + + + Push button for Jami SIP account creation start trigger + + + + + Create a SIP account + + + + + Link this device to an existing account + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Ubuntu'; font-size:14px; color:#555555;">To link this device to another account, you first </span><span style=" font-family:'Ubuntu'; font-size:14px; font-weight:600; color:#555555;">need to obtain a PIN</span><span style=" font-family:'Ubuntu'; font-size:14px; color:#555555;"> code. To generate the PIN code:</span></p> +<ol style="margin-top: 0px; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; -qt-list-indent: 1;"><li style=" font-family:'Ubuntu'; font-size:14px; color:#555555;" style=" margin-top:12px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:14px;">Go to the </span><span style=" font-size:14px; font-weight:600;">Account management setting</span><span style=" font-size:14px;"> of a previous device</span></li> +<li style=" font-family:'Ubuntu'; font-size:14px; color:#555555;" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:14px;">Choose the </span><span style=" font-size:14px; font-weight:600;">Jami account</span><span style=" font-size:14px;"> you want to use</span></li> +<li style=" font-family:'Ubuntu'; font-size:14px; color:#555555;" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:14px;">Go to the </span><span style=" font-size:14px; font-weight:600;">Devices</span><span style=" font-size:14px;"> tab</span></li> +<li style=" font-family:'Ubuntu'; font-size:14px; color:#555555;" style=" margin-top:0px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:14px;">Select </span><span style=" font-size:14px; font-weight:600;">Add a device</span></li></ol> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Ubuntu'; font-size:14px; color:#555555;">You will get the necessary PIN to complete this form. The PIN is only valid for </span><span style=" font-family:'Ubuntu'; font-size:14px; font-weight:600; color:#555555;">10 minutes</span><span style=" font-family:'Ubuntu'; font-size:10px; color:#555555;">.</span></p></body></html> + + + + + Enter your pin: + + + + + Or import a file: + + + + + Link from exported account archive file + + + + + + + (None) + + + + + Password: + + + + + + Profile + + + + + + Profile name + + + + + Account + + + + + Register your username. +This will reserve the username so that only you can use it. +Your friends will be able to call you with your usename +instead of using your ID. + + + + + Public username checkbox + + + + + Checkbox selecting if the user wants a public username + + + + + Register public username + + + + + Public username edit + + + + + Choose your username + + + + + Password text input + + + + + Password text entry + + + + + + Password + + + + + + Password confirmation text input + + + + + Confirm password + + + + + SIP Account + + + + + SIP Server edit + + + + + Server + + + + + SIP proxy input + + + + + SIP proxy text entry + + + + + Proxy + + + + + SIP username input + + + + + SIP Password text entry + + + + + Username + + + + + + SIP Password text input + + + + + Generating your Jami account… + + + + + Previous page button + + + + + push button to access previous page of wizard + + + + + Previous + + + + + Cancel account create/link + + + + + push button to cancel account creation or linking + + + + + Back + + + + + Next page Button + + + + + Push button to access next page of wizard + + + + + Next + + + + + Open File + + + + + Jami archive files (*.gz); All files (*) + + + + + Your account needs to be migrated. Enter your password. + + + + + Migrating your Jami account... + + + + + Importing account archive... + + + + + Generating your Jami account... + + + + + Generating your SIP account... + + + + + Error creating account + + + + + PasswordDialog + + + Change Account Password + + + + + Enter Current Password + + + + + Enter New Password + + + + + Confirm New Password + + + + + Confirm + + + + + Cancel + + + + + Current Password Incorrect + + + + + PhotoBoothDialog + + + Photobooth + + + + + PhotoboothWidget + + + Form + + + + + Photobooth display + + + + + Choose File + + + + + Image Files (*.jpg *.jpeg *.png) + + + + + PrivateBridging + + + Choose File + + + + + Files (*) + + + + + QObject + + + No default mail client found + + + + + + Edit Device Name + + + + + Unlink Device From Account + + + + + Save new device name + + + + + Add as contact + + + + + RingButton + + + Select folder + + + + + SettingsWidget + + + Form + + + + + Settings + + + + + Account + + + + + + General + + + + + + Audio / Video + + + + + System + + + + + Enable desktop notifications + + + + + Keep minimized on close + + + + + Download folder + + + + + Save in + + + + + Always Recording + + + + + Updates + + + + + Check for updates automatically every + + + + + Interval between update checks in days selector + + + + + days + + + + + Check for updates now button + + + + + Check for updates now + + + + + Password + + + + + + Enable + + + + + toggle enable notifications + + + + + Toggle keep minimized on close + + + + + Call Recordings + + + + + Toggle automatic updates + + + + + Jami Account + + + + + + Profile + + + + + + Identity + + + + + Id + + + + + Registered name + + + + + Type here to register a username + + + + + Register + + + + + Change Password + + + + + Export Account + + + + + + Delete Account + + + + + Linked Devices + + + + + Link Another Device + + + + + Banned Contacts + + + + + Format + + + + + Video device framerate selector + + + + + Preview unavailable + + + + + + Advanced Account Settings + + + + + SIP Account + + + + + Username + + + + + Hostname + + + + + Proxy + + + + + Audio + + + + + Microphone + + + + + Audio input device selector + + + + + Output Device + + + + + Choose the output device + + + + + Video + + + + + Device + + + + + Video device selector + + + + + A registered name should not have any spaces and must be at least three letters long + + + + + This name is already taken + + + + + + Enter an alias + + + + + Register this name + + + + + Remove Device + + + + + Enter this account's password to confirm the removal of this device + + + + + Are you sure you wish to remove this device? + + + + + Export Account Here + + + + + Select A Folder For Your Downloads + + + + + Select A Folder For Your Recordings + + + + + VideoOverlay + + + Call on Hold + + + + + Hold / Unhold + + + + + Chat + + + + + Mute Mic + + + + + Record call + + + + + Name label + + + + + Time elapsed + + + + + 00:00 + + + + + Hangup + + + + + Mute Video + + + + + VideoView + + + Share entire screen + + + + + Share screen area + + + + + Share file + + + + diff --git a/translations/ring_client_windows_eu.ts b/translations/ring_client_windows_eu.ts new file mode 100644 index 00000000..a50d2c9f --- /dev/null +++ b/translations/ring_client_windows_eu.ts @@ -0,0 +1,1589 @@ + + + AboutDialog + + + + About + Honi buruz + + + + about button + + + + + credits button + + + + + Credits + Kredituak + + + + Free as in Freedom + + + + + The Microsoft Windows client for Jami. +Jami is a secured and distributed communication software. + + + + + version + bertsioa + + + + Created by: + + + + + Artwork by: + + + + + Based on the SFLPhone project + + + + + AccountItemDelegate + + + Add Account + Gehitu kontua + + + + AdvancedSIPSettingsWidget + + + Form + + + + + Call Settings + + + + + Auto Answer Calls + + + + + Enable Custom Ringtone + + + + + Connectivity + + + + + STUN Address + + + + + Use STUN + + + + + Use UPnP + + + + + Use TURN + + + + + TURN Password + + + + + TURN Username + + + + + TURN Address + + + + + Media + Multimedia + + + + Enable Video + Gaitu bideoa + + + + Video Codecs + + + + + Audio Codecs + + + + + Audio Files (*.wav *.ogg *.opus *.mp3 *aiff *wma) + + + + + Add a custom ringtone + + + + + AdvancedSettingsWidget + + + Form + + + + + Call Settings + + + + + Allow Calls From Untrusted Peers + + + + + Auto Answer Calls + + + + + Enable Custom Ringtone + + + + + Add a custom ringtone + + + + + Name Server + + + + + Address + Helbidea + + + + OpenDHT Configuration + + + + + Enable Proxy + + + + + Bootstrap + + + + + Security + Segurtasuna + + + + Private Key Password + Gako pribatuaren pasahitza + + + + User Certificate + + + + + Private Key + Gako pribatua + + + + CA Certificate + CA ziurtagiria + + + + Connectivity + + + + + Use STUN + + + + + STUN Address + + + + + Use UPnP + + + + + Use TURN + + + + + TURN Password + + + + + TURN Username + + + + + TURN Address + + + + + Media + Multimedia + + + + Enable Video + Gaitu bideoa + + + + Audio Codecs + + + + + Video Codecs + + + + + Audio Files (*.wav *.ogg *.opus *.mp3 *aiff *wma) + + + + + AnimatedOverlay + + + Form + + + + + BannedItemWidget + + + Form + + + + + name + + + + + id + + + + + CallWidget + + + Show conversations + Erakutsi elkarrizketa + + + + Conversations + Elkarrizketak + + + + Search contact text input + + + + + Jami is free software for universal communication which respects the freedoms and privacy of its users. + Jami komunikazio unibertsalerako software librea da, erabiltzaileek askatasunak eta pribatutasuna aintzat hartzen dituena + + + + + This is your ID. +Copy and share it with your friends! + + + + + + Show ring ID QR code + + + + + Share ring ID button + + + + + Double-click to copy + + + + + Error while generating QR Code + + + + + + best name + + + + + best Id + + + + + Back to homepage button + + + + + Add to contacts + Gehitu kontaktuetara + + + + Show invites + + + + + Invites + + + + + + Find a new or existing contact + + + + + Wants to talk to you! + Zurekin hitz egin nahi du! + + + + Answer incoming call button + + + + + Ignore incoming call button + + + + + Answer + Erantzun + + + + Ignore + Ezikusi + + + + Cancel outgoing call + + + + + Cancel + Ezeztatu + + + + Start video call + Hasi bideo-deia + + + + Start audio call + Hasi audio-deia + + + + Clear conversation + + + + + Remove contact + Kendu kontaktua + + + + Block contact + Blokeatu kontaktua + + + + Copy number + Kopiatu zenbakia + + + + Search your received invitations + + + + + Contact me on Jami + + + + + My Id is : + + + + + %1 + %1 is the contact username + %1 + + + + %1 + %1 is the contact unique identifier + %1 + + + + Call incoming from %1 + + + + + DeleteAccountDialog + + + Account deletion + + + + + Do you really want to delete the following account? + + + + + If this account hasn't been exported, or added to another device, it will be irrevocably lost. + + + + + Permanently delete account + + + + + Delete + Ezabatu + + + + Cancel account deletion + + + + + Cancel + Ezeztatu + + + + DeviceItemWidget + + + Form + + + + + Device Id + + + + + this device + gailu hau + + + + InviteButtonsWidget + + + Accept + Onartu + + + + Refuse + Ukatu + + + + Block + Bloketu + + + + LinkDeviceDialog + + + Dialog + + + + + Enter your account password + + + + + Password + Pasahitza + + + + Ok + Ados + + + + Cancel + Ezeztatu + + + + Exporting account + + + + + Your PIN is + + + + + PIN + PIN-a + + + + This pin and the account password should be entered in your device within 10 minutes. + + + + + Close + Itxi + + + + Link Another Device + + + + + Incorrect password + + + + + Something went wrong. +Please try again later. + + + + + MainWindow + + + Settings + Ezarpenak + + + + Exit + Irten + + + + About + Honi buruz + + + + Jami + Jami + + + + NameRegistrationDialog + + + Set Registered Name + + + + + Enter your account password + + + + + Password text input + + + + + Password text entry + + + + + Password + Pasahitza + + + + Register + Erregistratu + + + + Cancel + Ezeztatu + + + + Registering Name + + + + + Something went wrong + + + + + Close + Itxi + + + + Incorrect password + + + + + Network error + Sare errorea + + + + NewWizardWidget + + + Form + + + + + Welcome Label + + + + + Welcome to + + + + + Welcome Logo + + + + + Create Jami account button + + + + + Push button for Jami account creation start trigger + + + + + Create a Jami account + Sortu Jami kontua + + + + Link device button + + + + + Push button for device linkage start trigger + + + + + Link this device to an account + Estekatu gailua kontu batekin + + + + Create Jami SIP account button + + + + + Push button for Jami SIP account creation start trigger + + + + + Create a SIP account + + + + + Link this device to an existing account + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Ubuntu'; font-size:14px; color:#555555;">To link this device to another account, you first </span><span style=" font-family:'Ubuntu'; font-size:14px; font-weight:600; color:#555555;">need to obtain a PIN</span><span style=" font-family:'Ubuntu'; font-size:14px; color:#555555;"> code. To generate the PIN code:</span></p> +<ol style="margin-top: 0px; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; -qt-list-indent: 1;"><li style=" font-family:'Ubuntu'; font-size:14px; color:#555555;" style=" margin-top:12px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:14px;">Go to the </span><span style=" font-size:14px; font-weight:600;">Account management setting</span><span style=" font-size:14px;"> of a previous device</span></li> +<li style=" font-family:'Ubuntu'; font-size:14px; color:#555555;" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:14px;">Choose the </span><span style=" font-size:14px; font-weight:600;">Jami account</span><span style=" font-size:14px;"> you want to use</span></li> +<li style=" font-family:'Ubuntu'; font-size:14px; color:#555555;" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:14px;">Go to the </span><span style=" font-size:14px; font-weight:600;">Devices</span><span style=" font-size:14px;"> tab</span></li> +<li style=" font-family:'Ubuntu'; font-size:14px; color:#555555;" style=" margin-top:0px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:14px;">Select </span><span style=" font-size:14px; font-weight:600;">Add a device</span></li></ol> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Ubuntu'; font-size:14px; color:#555555;">You will get the necessary PIN to complete this form. The PIN is only valid for </span><span style=" font-family:'Ubuntu'; font-size:14px; font-weight:600; color:#555555;">10 minutes</span><span style=" font-family:'Ubuntu'; font-size:10px; color:#555555;">.</span></p></body></html> + + + + + Enter your pin: + + + + + Or import a file: + + + + + Link from exported account archive file + + + + + + + (None) + (Bat ere ez) + + + + Password: + Pasahitza: + + + + + Profile + Profila + + + + + Profile name + + + + + Account + Kontua + + + + Register your username. +This will reserve the username so that only you can use it. +Your friends will be able to call you with your usename +instead of using your ID. + + + + + Public username checkbox + + + + + Checkbox selecting if the user wants a public username + + + + + Register public username + Erregistratu izen publikoa + + + + Public username edit + + + + + Choose your username + + + + + Password text input + + + + + Password text entry + + + + + + Password + Pasahitza + + + + + Password confirmation text input + + + + + Confirm password + Berretsi pasahitza + + + + SIP Account + + + + + SIP Server edit + + + + + Server + + + + + SIP proxy input + + + + + SIP proxy text entry + + + + + Proxy + Proxya + + + + SIP username input + + + + + SIP Password text entry + + + + + Username + Erabiltzaile-izena + + + + + SIP Password text input + + + + + Generating your Jami account… + + + + + Previous page button + + + + + push button to access previous page of wizard + + + + + Previous + Aurrekoa + + + + Cancel account create/link + + + + + push button to cancel account creation or linking + + + + + Back + Atzera + + + + Next page Button + + + + + Push button to access next page of wizard + + + + + Next + Hurrengoa + + + + Open File + Ireki fitxategia + + + + Jami archive files (*.gz); All files (*) + + + + + Your account needs to be migrated. Enter your password. + + + + + Migrating your Jami account... + + + + + Importing account archive... + + + + + Generating your Jami account... + + + + + Generating your SIP account... + + + + + Error creating account + + + + + PasswordDialog + + + Change Account Password + + + + + Enter Current Password + + + + + Enter New Password + Sartu pasahitz berria + + + + Confirm New Password + Baieztatu pasahitz berria + + + + Confirm + + + + + Cancel + Ezeztatu + + + + Current Password Incorrect + + + + + PhotoBoothDialog + + + Photobooth + + + + + PhotoboothWidget + + + Form + + + + + Photobooth display + + + + + Choose File + Hautatu fitxategia + + + + Image Files (*.jpg *.jpeg *.png) + + + + + PrivateBridging + + + Choose File + Hautatu fitxategia + + + + Files (*) + + + + + QObject + + + No default mail client found + + + + + + Edit Device Name + + + + + Unlink Device From Account + + + + + Save new device name + + + + + Add as contact + + + + + RingButton + + + Select folder + Hautatu karpeta + + + + SettingsWidget + + + Form + + + + + Settings + Ezarpenak + + + + Account + Kontua + + + + + General + Orokorra + + + + + Audio / Video + + + + + System + Sistema + + + + Enable desktop notifications + + + + + Keep minimized on close + + + + + Download folder + + + + + Save in + + + + + Always Recording + + + + + Updates + Eguneratzeak + + + + Check for updates automatically every + + + + + Interval between update checks in days selector + + + + + days + + + + + Check for updates now button + + + + + Check for updates now + + + + + Password + Pasahitza + + + + + Enable + Gaitu + + + + toggle enable notifications + + + + + Toggle keep minimized on close + + + + + Call Recordings + + + + + Toggle automatic updates + + + + + Jami Account + + + + + + Profile + Profila + + + + + Identity + Identitatea + + + + Id + + + + + Registered name + + + + + Type here to register a username + + + + + Register + Erregistratu + + + + Change Password + Aldatu pasahitza + + + + Export Account + + + + + + Delete Account + Ezabatu kontua + + + + Linked Devices + + + + + Link Another Device + + + + + Banned Contacts + + + + + Format + + + + + Video device framerate selector + + + + + Preview unavailable + + + + + + Advanced Account Settings + + + + + SIP Account + + + + + Username + Erabiltzaile-izena + + + + Hostname + Ostalari-izena + + + + Proxy + Proxya + + + + Audio + Audioa + + + + Microphone + Mikrofonoa + + + + Audio input device selector + + + + + Output Device + Irteera gailua + + + + Choose the output device + + + + + Video + Bideoa + + + + Device + Gailua + + + + Video device selector + + + + + A registered name should not have any spaces and must be at least three letters long + + + + + This name is already taken + + + + + + Enter an alias + + + + + Register this name + + + + + Remove Device + + + + + Enter this account's password to confirm the removal of this device + + + + + Are you sure you wish to remove this device? + + + + + Export Account Here + + + + + Select A Folder For Your Downloads + + + + + Select A Folder For Your Recordings + + + + + VideoOverlay + + + Call on Hold + + + + + Hold / Unhold + + + + + Chat + Txata + + + + Mute Mic + + + + + Record call + + + + + Name label + + + + + Time elapsed + + + + + 00:00 + 00:00 + + + + Hangup + Eseki + + + + Mute Video + + + + + VideoView + + + Share entire screen + + + + + Share screen area + + + + + Share file + Partekatu fitxategia + + + \ No newline at end of file diff --git a/translations/ring_client_windows_fa_IR.ts b/translations/ring_client_windows_fa_IR.ts new file mode 100644 index 00000000..a31c68bf --- /dev/null +++ b/translations/ring_client_windows_fa_IR.ts @@ -0,0 +1,1602 @@ + + + AboutDialog + + + + About + درباره + + + + about button + دکمه درباره + + + + credits button + دکمه دست‌اندرکاران + + + + Credits + دست‌اندرکاران + + + + Free as in Freedom + آزاد مانند آزادی + + + + The Microsoft Windows client for Jami. +Jami is a secured and distributed communication software. + سرویس‌گیرنده ویندوز مایکروسافت برای جمی. +جمی یک نرم افزار ارتباطی امن و توزیع شده است. + + + + version + نسخه + + + + Created by: + ساخته‌شده توسط: + + + + Artwork by: + اثر هنری توسط: + + + + Based on the SFLPhone project + برمبنای پروژه SFLPhone + + + + AccountItemDelegate + + + Add Account + افزودن حساب + + + + AdvancedSIPSettingsWidget + + + Form + فرم + + + + Call Settings + تنظیمات تماس + + + + Auto Answer Calls + پاسخگویی خودکار تماس‌ها + + + + Enable Custom Ringtone + فعال‌سازی صدای زنگ سفارشی + + + + Connectivity + اتصال + + + + STUN Address + نشانی STUN + + + + Use STUN + استفاده از STUN + + + + Use UPnP + استفاده از UPnP + + + + Use TURN + استفاده از TURN + + + + TURN Password + گذرواژه TURN + + + + TURN Username + نام کاربری TURN + + + + TURN Address + نشانی TURN + + + + Media + رسانه + + + + Enable Video + فعّال کردن ویدیو + + + + Video Codecs + کدک‌های ویدیویی + + + + Audio Codecs + رمزینه‌های صوتی + + + + Audio Files (*.wav *.ogg *.opus *.mp3 *aiff *wma) + فایل‌های صوتی (‎*.wav *.ogg *.opus *.mp3 *.aiff *.wma‎) + + + + Add a custom ringtone + افزودن یک صدای زنگ سفارشی + + + + AdvancedSettingsWidget + + + Form + فرم + + + + Call Settings + تنظیمات تماس + + + + Allow Calls From Untrusted Peers + اجازه تماس به همتاهای ناشناخته + + + + Auto Answer Calls + پاسخگویی خودکار تماس‌ها + + + + Enable Custom Ringtone + فعال‌سازی صدای زنگ سفارشی + + + + Add a custom ringtone + افزودن یک صدای زنگ سفارشی + + + + Name Server + سرور نام + + + + Address + نشانی + + + + OpenDHT Configuration + پکربندی OpenDHT + + + + Enable Proxy + فعال سازی پروکسی + + + + Bootstrap + خود راه اندازی + + + + Security + امنیت + + + + Private Key Password + گذرواژه کلید خصوصی + + + + User Certificate + گواهی کاربر + + + + Private Key + کلید خصوصی + + + + CA Certificate + گواهی CA + + + + Connectivity + اتصال + + + + Use STUN + استفاده از STUN + + + + STUN Address + نشانی STUN + + + + Use UPnP + استفاده از UPnP + + + + Use TURN + استفاده از TURN + + + + TURN Password + گذرواژه TURN + + + + TURN Username + نام‌کاربری TURN + + + + TURN Address + نشانی TURN + + + + Media + رسانه + + + + Enable Video + فعّال کردن ویدیو + + + + Audio Codecs + رمزینه‌های صوتی + + + + Video Codecs + کدک‌های ویدیویی + + + + Audio Files (*.wav *.ogg *.opus *.mp3 *aiff *wma) + فایل‌های صوتی (‎*.wav *.ogg *.opus *.mp3 *.aiff *.wma‎) + + + + AnimatedOverlay + + + Form + فرم + + + + BannedItemWidget + + + Form + فرم + + + + name + نام + + + + id + شناسه + + + + CallWidget + + + Show conversations + نمایش گفتگو‌ها + + + + Conversations + گفتگو‌ها + + + + Search contact text input + جستجوی متن ورودی مخاطب + + + + Jami is free software for universal communication which respects the freedoms and privacy of its users. + جمی نرم‌افزار آزاد برای ارتباط جهانی است که به آزادی‌ها و محرمانگی کاربرانش احترام می‌گذارد. + + + + + This is your ID. +Copy and share it with your friends! + + +این شناسه شماست. +آن را کپی کنید و با دوستان خود به اشتراک بگذارید! + + + + + Show ring ID QR code + نمایش کد QR شناسه رینگ + + + + Share ring ID button + به اشتراک گذاری دکمه آیدی رینگ + + + + Double-click to copy + برای کپی کردن دو بار کلیک کنید + + + + Error while generating QR Code + خطا در هنگام تولید کد QR + + + + + best name + بهترین نام + + + + best Id + بهترین شناسه + + + + Back to homepage button + دکمه برگشت به صفحه نخست + + + + Add to contacts + افزودن به مخاطبان + + + + Show invites + نمایش دعوت ها + + + + Invites + دعوت ها + + + + + Find a new or existing contact + یافتن مخاطب جدید یا موجود + + + + Wants to talk to you! + میخواهد با شما حرف بزند! + + + + Answer incoming call button + دکمه پاسخ به تماس ورودی + + + + Ignore incoming call button + دکمه نادیده گرفتن تماس ورودی + + + + Answer + پاسخ + + + + Ignore + رد + + + + Cancel outgoing call + لغو تماس خروجی + + + + Cancel + لغو + + + + Start video call + شروع تماس ویدیویی + + + + Start audio call + شروع تماس صوتی + + + + Clear conversation + پاک کردن گفتگو + + + + Remove contact + حذف مخاطب + + + + Block contact + مسدودسازی مخاطب + + + + Copy number + رونوشت از شماره + + + + Search your received invitations + جستجوی دعوت نامه‌های دریافت‌شده شما + + + + Contact me on Jami + با من روی جمی در تماس باشید! + + + + My Id is : + شناسه من: + + + + %1 + %1 is the contact username + %1 + + + + %1 + %1 is the contact unique identifier + %1 + + + + Call incoming from %1 + تماس ورودی از %1 + + + + DeleteAccountDialog + + + Account deletion + حذف حساب + + + + Do you really want to delete the following account? + آیا واقعا می‌خواهید حساب زیر را پاک کنید؟ + + + + If this account hasn't been exported, or added to another device, it will be irrevocably lost. + اگر این حساب برون‌برد نشده یا به دستگاه دیگری اضافه نشده باشد، برگشت‌ناپذیر خواهد بود. + + + + Permanently delete account + حذف حساب برای همیشه + + + + Delete + حذف + + + + Cancel account deletion + لغو حذف حساب + + + + Cancel + لغو + + + + DeviceItemWidget + + + Form + فرم + + + + Device Id + شناسه دستگاه + + + + this device + این دستگاه + + + + InviteButtonsWidget + + + Accept + پذیرش + + + + Refuse + رد + + + + Block + مسدود + + + + LinkDeviceDialog + + + Dialog + گفتگو + + + + Enter your account password + گذرواژه حساب‌تان را وارد کنید + + + + Password + گذرواژه + + + + Ok + باشه + + + + Cancel + لغو + + + + Exporting account + برون‌برد حساب + + + + Your PIN is + پین شما + + + + PIN + پین + + + + This pin and the account password should be entered in your device within 10 minutes. + این پین و گذرواژه حساب باید ظرف 10 دقیقه در دستگاه شما وارد شود. + + + + Close + بستن + + + + Link Another Device + پیوند یک دستگاه دیگر + + + + Incorrect password + گذرواژه ناصحیح + + + + Something went wrong. +Please try again later. + مشکلی پیش آمد. + لطفا بعدا دوباره امتحان کنید. + + + + MainWindow + + + Settings + تنظیمات + + + + Exit + خروج + + + + About + درباره + + + + Jami + جمی + + + + NameRegistrationDialog + + + Set Registered Name + تنظیم نام ثبت‌شده + + + + Enter your account password + گذرواژه حساب‌تان را وارد کنید + + + + Password text input + ورودی متن گذرواژه + + + + Password text entry + ورودی متن گذرواژه + + + + Password + گذرواژه + + + + Register + ثبت‌نام + + + + Cancel + لغو + + + + Registering Name + ثبت نام + + + + Something went wrong + مشکلی پیش آمد. + + + + Close + بستن + + + + Incorrect password + گذرواژه ناصحیح + + + + Network error + خطای شبکه + + + + NewWizardWidget + + + Form + فرم + + + + Welcome Label + برچست خوش آمد + + + + Welcome to + خوش آمدید به + + + + Welcome Logo + لوگو خوش آمد + + + + Create Jami account button + دکمه ایجاد حساب جمی + + + + Push button for Jami account creation start trigger + راه‌انداز دکمه فشاری برای ایجاد حساب جمی + + + + Create a Jami account + ایجاد یک حساب جمی + + + + Link device button + دکمه پیوند دستگاه + + + + Push button for device linkage start trigger + راه‌انداز دکمه فشاری برای پیوند دستگاه + + + + Link this device to an account + پیوند این دستگاه به یک حساب + + + + Create Jami SIP account button + دکمه ایجاد حساب SIP + + + + Push button for Jami SIP account creation start trigger + راه‌انداز دکمه فشاری برای ایجاد حساب SIP جمی + + + + Create a SIP account + ایجاد یک حساب SIP + + + + Link this device to an existing account + پیوند این دستگاه به یک حساب کاربری موجود + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Ubuntu'; font-size:14px; color:#555555;">To link this device to another account, you first </span><span style=" font-family:'Ubuntu'; font-size:14px; font-weight:600; color:#555555;">need to obtain a PIN</span><span style=" font-family:'Ubuntu'; font-size:14px; color:#555555;"> code. To generate the PIN code:</span></p> +<ol style="margin-top: 0px; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; -qt-list-indent: 1;"><li style=" font-family:'Ubuntu'; font-size:14px; color:#555555;" style=" margin-top:12px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:14px;">Go to the </span><span style=" font-size:14px; font-weight:600;">Account management setting</span><span style=" font-size:14px;"> of a previous device</span></li> +<li style=" font-family:'Ubuntu'; font-size:14px; color:#555555;" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:14px;">Choose the </span><span style=" font-size:14px; font-weight:600;">Jami account</span><span style=" font-size:14px;"> you want to use</span></li> +<li style=" font-family:'Ubuntu'; font-size:14px; color:#555555;" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:14px;">Go to the </span><span style=" font-size:14px; font-weight:600;">Devices</span><span style=" font-size:14px;"> tab</span></li> +<li style=" font-family:'Ubuntu'; font-size:14px; color:#555555;" style=" margin-top:0px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:14px;">Select </span><span style=" font-size:14px; font-weight:600;">Add a device</span></li></ol> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Ubuntu'; font-size:14px; color:#555555;">You will get the necessary PIN to complete this form. The PIN is only valid for </span><span style=" font-family:'Ubuntu'; font-size:14px; font-weight:600; color:#555555;">10 minutes</span><span style=" font-family:'Ubuntu'; font-size:10px; color:#555555;">.</span></p></body></html> + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; }</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Ubuntu'; font-size:14px; color:#555555;">برای پیوند این دستگاه به حسابی دیگر شما در ابتدا </span><span style=" font-family:'Ubuntu'; font-size:14px; font-weight:600; color:#555555;">نیاز است کد پین را تولید کنید.</span><span style=" font-family:'Ubuntu'; font-size:14px; color:#555555;"> برای تولید کد پین:</span></p> +<ol style="margin-top: 0px; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; -qt-list-indent: 1;"><li style=" font-family:'Ubuntu'; font-size:14px; color:#555555;" style=" margin-top:12px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:14px;">به </span><span style=" font-size:14px; font-weight:600;">تنظیمات مدیریت حساب</span><span style=" font-size:14px;"> در دستگاه قبلی رفته،</li> +<li style=" font-family:'Ubuntu'; font-size:14px; color:#555555;" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:14px;">حساب جمی را </span><span style=" font-size:14px; font-weight:600;">که می‌خواهید استفاده کنید،</span><span style=" font-size:14px;"> انتخاب کنید</span></li><li style=" font-family:'Ubuntu'; font-size:14px; color:#555555;" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:14px;">‌به برگه </span><span style=" font-size:14px; font-weight:600;">دستگاه‌ها</span><span style=" font-size:14px;"> بروید و افزودن یک دستگاه را </span>انتخاب کنید</span></li></ol> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Ubuntu'; font-size:14px; color:#555555;">شما پین لازم برای تکمیل این فرم را دریافت خواهید کرد که تنها برای </span>10 دقیقه معتبر خواهد بود<span style=" font-family:'Ubuntu'; font-size:10px; color:#555555;">.</span></p></body></html> + + + + Enter your pin: + پین خود را وارد کنید: + + + + Or import a file: + یا درون‌ریزی یک پرونده: + + + + Link from exported account archive file + پیوند از فایل بایگانی حساب برون‌برد‌شده + + + + + + (None) + (هیچ) + + + + Password: + گذرواژه: + + + + + Profile + نمایه + + + + + Profile name + نام نمایه + + + + Account + حساب کاربری + + + + Register your username. +This will reserve the username so that only you can use it. +Your friends will be able to call you with your usename +instead of using your ID. + نام‌کاربری خود را ثبت کنید. +با این کار نام‌کاربری رزرو می‌شود تا فقط شما بتوانید از آن استفاده کنید. + دوستان شما می‌توانند به جای استفاده از شناسه شما با نام‌کاربری‌تان با شما تماس بگیرند. + + + + Public username checkbox + چک‌باکس نام‌کاربری عمومی + + + + Checkbox selecting if the user wants a public username + چک‌باکس انتخاب اینکه آیا کاربر یک نام‌کاربری عمومی می‌خواهد + + + + Register public username + ثبت نام‌کاربری عمومی + + + + Public username edit + ویرایش نام کاربری عمومی + + + + Choose your username + نام کاربری خود را انتخاب کنید + + + + Password text input + ورودی متن گذرواژه + + + + Password text entry + ورودی متن گذرواژه + + + + + Password + گذرواژه + + + + + Password confirmation text input + متن وارد‌شده تایید گذرواژه + + + + Confirm password + تأیید گذرواژه + + + + SIP Account + حساب کاربری سیپ + + + + SIP Server edit + ویرایش سرور SIP + + + + Server + سرور + + + + SIP proxy input + پروکسی SIP وارد‌شده + + + + SIP proxy text entry + ورودی متن پروکسی SIP + + + + Proxy + پیشکار یا پروکسی + + + + SIP username input + ورودی نام کاربری SIP + + + + SIP Password text entry + ورودی متن گذرواژه SIP + + + + Username + نام کاربری + + + + + SIP Password text input + متن گذرواژه SIP وارد‌شده + + + + Generating your Jami account… + تولید حساب جمی شما... + + + + Previous page button + دکمه صفحه قبلی + + + + push button to access previous page of wizard + دکمه فشاری برای دسترسی به صفحه قبلی wizard + + + + Previous + پیشین + + + + Cancel account create/link + لغو ساخت/پیوند حساب + + + + push button to cancel account creation or linking + دکمه فشاری برای لغو ایجاد یا پیوند حساب + + + + Back + بازگشت + + + + Next page Button + دکمه صفحه بعد + + + + Push button to access next page of wizard + دکمه فشاری برای دسترسی به صفحه بعدی wizard + + + + Next + بعدی + + + + Open File + باز کردن فایل + + + + Jami archive files (*.gz); All files (*) + فایل‌های بایگانی جمی (‎*.gz)؛ تمام فایلها (*) + + + + Your account needs to be migrated. Enter your password. + نیاز است که حساب شما انتقال یابد. گذرواژه خود را وارد کنید. + + + + Migrating your Jami account... + در حال انتقال حساب جمی شما... + + + + Importing account archive... + ورود بایگانی حساب... + + + + Generating your Jami account... + تولید حساب جمی شما... + + + + Generating your SIP account... + تولید حساب SIP شما... + + + + Error creating account + خطای ایجاد حساب + + + + PasswordDialog + + + Change Account Password + تغییر گذرواژه حساب + + + + Enter Current Password + ورود گذرواژه فعلی + + + + Enter New Password + ورود گذرواژه جدید + + + + Confirm New Password + تایید گذرواژه جدید + + + + Confirm + تایید + + + + Cancel + لغو + + + + Current Password Incorrect + گذرواژه فعلی نادرست است. + + + + PhotoBoothDialog + + + Photobooth + غرفه عکس + + + + PhotoboothWidget + + + Form + فرم + + + + Photobooth display + نمایش غرفه عکس + + + + Choose File + انتخاب فایل + + + + Image Files (*.jpg *.jpeg *.png) + فایل‌های تصویر (‎*.jpg *.jpeg *.png) + + + + PrivateBridging + + + Choose File + انتخاب فایل + + + + Files (*) + فایل‌ها (*) + + + + QObject + + + No default mail client found + هیچ سرویس‌گیرنده ایمیل پیش‌فرضی یافت نشد + + + + + Edit Device Name + ویرایش نام دستگاه + + + + Unlink Device From Account + حذف پیوند دستگاه به حساب + + + + Save new device name + ذخیره نام جدید دستگاه + + + + Add as contact + افزودن به عنوان مخاطب + + + + RingButton + + + Select folder + انتخاب پوشه + + + + SettingsWidget + + + Form + فرم + + + + Settings + تنظیمات + + + + Account + حساب کاربری + + + + + General + عمومی + + + + + Audio / Video + صدا / تصویر + + + + System + سامانه + + + + Enable desktop notifications + فعال‌سازی اعلان‌ها + + + + Keep minimized on close + در هنگام بستن کمینه نگه دار + + + + Download folder + شاخهٔ بارگیری + + + + Save in + ذخیره کن در + + + + Always Recording + همیشه در حال ضبط + + + + Updates + به‌روزرسانی‌ها + + + + Check for updates automatically every + بررسی خودکار به‌روزرسانی‌ها هر + + + + Interval between update checks in days selector + انتخاب‌گر بازه بین بررسی‌های برای به‌روزرسانی در واحد روز + + + + days + روز + + + + Check for updates now button + دکمه همین الان برروزرسانی ها را چک کن + + + + Check for updates now + به‌روزرسانی‌ها را همین الان بررسی کن + + + + Password + گذرواژه + + + + + Enable + فعال‌سازی + + + + toggle enable notifications + تغییر وضعیت فعال‌سازی اعلان‌ها + + + + Toggle keep minimized on close + تغییر وضعیت کمینه نگه داشتن در هنگام بستن + + + + Call Recordings + تماس‌های ضبط‌شده + + + + Toggle automatic updates + تغییر وضعیت به‌روزرسانی‌های خودکار + + + + Jami Account + حساب جمی + + + + + Profile + نمایه + + + + + Identity + هویت + + + + Id + شناسایی ID + + + + Registered name + نام ثبت شده + + + + Type here to register a username + برای ثبت نام‌کاربری اینجا بنویسید + + + + Register + ثبت‌نام + + + + Change Password + تغییر گذرواژه + + + + Export Account + برون‌برد (ذخیره) حساب + + + + + Delete Account + حذف حساب + + + + Linked Devices + دستگاه‌های پیوند‌داده‌شده + + + + Link Another Device + پیوند یک دستگاه دیگر + + + + Banned Contacts + مخاطبان مسدود شده + + + + Format + قالب + + + + Video device framerate selector + انتخاب‌گر نرخ فریم دستگاه ویدیویی + + + + Preview unavailable + پیش‌نمایش در‌دسترس نیست + + + + + Advanced Account Settings + تنظیمات پیش‌رفته حساب + + + + SIP Account + حساب کاربری سیپ + + + + Username + نام کاربری + + + + Hostname + نام میزبان + + + + Proxy + پیشکار یا پروکسی + + + + Audio + صدا + + + + Microphone + میکروفون + + + + Audio input device selector + انتخاب کننده دستگاه ورودی صوتی + + + + Output Device + دستگاه خروجی + + + + Choose the output device + انتخاب دستگاه خروجی + + + + Video + ویدیو + + + + Device + دستگاه + + + + Video device selector + انتخاب کننده دستگاه ویدیو + + + + A registered name should not have any spaces and must be at least three letters long + یک نام ثبت شده نمی‌بایست دارای هیچ فضای خالی بوده و حداقل دارای سه حرف باشد + + + + This name is already taken + این نام پیش از این گرفته شده است + + + + + Enter an alias + یک نام مستعار وارد کنید + + + + Register this name + تبت این نام + + + + Remove Device + حذف دستگاه + + + + Enter this account's password to confirm the removal of this device + گذرواژه این حساب را برای تایید حذف این دستگاه وارد کنید + + + + Are you sure you wish to remove this device? + اطمینان دارید که می‌خواهید این دستگاه را حذف کنید؟ + + + + Export Account Here + حساب را در اینجا برون‌برد کن + + + + Select A Folder For Your Downloads + یک پوشه برای دانلود‌های خود انتخاب کنید + + + + Select A Folder For Your Recordings + یک پوشه برای صدا‌های ضبط‌شده خود انتخاب کنید + + + + VideoOverlay + + + Call on Hold + تماس نگه‌داشته + + + + Hold / Unhold + نگه‌داشتن / رها کردن + + + + Chat + چت + + + + Mute Mic + قطع میکروفون + + + + Record call + ضبط تماس + + + + Name label + نامگذاری برچسب + + + + Time elapsed + زمان سپری شده + + + + 00:00 + 00:00 + + + + Hangup + به صحبت تلفنی خاتمه دادن + + + + Mute Video + بی‌صدا کردن ویدیو + + + + VideoView + + + Share entire screen + به اشتراک گذاری تمام صفحه نمایش + + + + Share screen area + ناحیه اشتراک صفحه + + + + Share file + هم‌رسانی پرونده + + + \ No newline at end of file diff --git a/translations/ring_client_windows_fi.ts b/translations/ring_client_windows_fi.ts new file mode 100644 index 00000000..f202c84f --- /dev/null +++ b/translations/ring_client_windows_fi.ts @@ -0,0 +1,1605 @@ + + + AboutDialog + + + + About + Tietoa + + + + about button + tietoja-painike + + + + credits button + tekijät -painike + + + + Credits + Tekijät + + + + Free as in Freedom + Ilmainen kuin vapaus + + + + The Microsoft Windows client for Jami. +Jami is a secured and distributed communication software. + Jami -sovellus Microsoft Windowsille. +Jami on turvallinen ja hajautettu viestintäsovellus. + + + + version + versio + + + + Created by: + Luonut: + + + + Artwork by: + Grafiikka: + + + + Based on the SFLPhone project + Pohjautuu SFLPhone-projektiin + + + + AccountItemDelegate + + + Add Account + Lisää tunnus + + + + AdvancedSIPSettingsWidget + + + Form + Muoto + + + + Call Settings + Puheluasetukset + + + + Auto Answer Calls + Vastaa puheluihin automaattisesti + + + + Enable Custom Ringtone + Oma soittoääni + + + + Connectivity + Yhteydet + + + + STUN Address + STUN osoite + + + + Use STUN + Käytä STUNia + + + + Use UPnP + Käytä UPnP + + + + Use TURN + Käytä TURNia + + + + TURN Password + TURN salasana + + + + TURN Username + TURN käyttäjänimi + + + + TURN Address + TURN osoite + + + + Media + Media + + + + Enable Video + Video päälle + + + + Video Codecs + Videokoodekit + + + + Audio Codecs + Äänikoodekit + + + + Audio Files (*.wav *.ogg *.opus *.mp3 *aiff *wma) + Äänitiedostot (*.wav *.ogg *.opus *.mp3 *aiff *wma) + + + + Add a custom ringtone + Lisää oma soittoääni + + + + AdvancedSettingsWidget + + + Form + Muoto + + + + Call Settings + Puheluasetukset + + + + Allow Calls From Untrusted Peers + Salli puhelut tuntemattomilta + + + + Auto Answer Calls + Vastaa puheluihin automaattisesti + + + + Enable Custom Ringtone + Oma soittoääni + + + + Add a custom ringtone + Lisää oma soittoääni + + + + Name Server + Nimipalvelin + + + + Address + Osoite + + + + OpenDHT Configuration + OpenDHT-määritykset + + + + Enable Proxy + Proxy käyttöön + + + + Bootstrap + Bootstrap + + + + Security + Turvallisuus + + + + Private Key Password + Salausavaimen salassana + + + + User Certificate + Käyttäjävarmenne + + + + Private Key + Henkilökohtainen salausavain + + + + CA Certificate + CA-varmenne + + + + Connectivity + Yhteydet + + + + Use STUN + Käytä STUNia + + + + STUN Address + STUN-osoite + + + + Use UPnP + Käytä UPnP + + + + Use TURN + Käytä TURNia + + + + TURN Password + TURN salasana + + + + TURN Username + TURN käyttäjänimi + + + + TURN Address + TURN osoite + + + + Media + Media + + + + Enable Video + Video päälle + + + + Audio Codecs + Äänikoodekit + + + + Video Codecs + Videokoodekit + + + + Audio Files (*.wav *.ogg *.opus *.mp3 *aiff *wma) + Äänitiedostot (*.wav *.ogg *.opus *.mp3 *aiff * wma) + + + + AnimatedOverlay + + + Form + Muoto + + + + BannedItemWidget + + + Form + Muoto + + + + name + nimi + + + + id + id + + + + CallWidget + + + Show conversations + Näytä keskustelu + + + + Conversations + Keskustelu + + + + Search contact text input + Hae yhteystieto tekstihaulla + + + + Jami is free software for universal communication which respects the freedoms and privacy of its users. + Jami on vapaa ja universaali viestintäalusta, joka kunnioittaa käyttäjiensä vapauksia ja yksityisyyttä. + + + + + This is your ID. +Copy and share it with your friends! + + +Tämä on sinun ID-tunnus. +Kopioi ja jaa se ystäviesi kanssa! + + + + Show ring ID QR code + Näytä ring ID QR-koodi + + + + Share ring ID button + Jaa ring ID -painike + + + + Double-click to copy + Kopioi kaksoisnapsauttamalla + + + + Error while generating QR Code + Virhe generoidessa QR-koodia + + + + + best name + paras nimi + + + + best Id + paras Id + + + + Back to homepage button + Takaisin kotisivulle -painike + + + + Add to contacts + Lisää yhteystietoihin + + + + Show invites + Näytä kutsut + + + + Invites + Kutsut + + + + + Find a new or existing contact + Etsi uusi tai olemassaoleva yhteystieto + + + + Wants to talk to you! + Haluaa puhua kanssasi! + + + + Answer incoming call button + Vastaa saapuvaan puheluun -painike + + + + Ignore incoming call button + Ohita saapuvan puhelun -painike + + + + Answer + Vastaa + + + + Ignore + Sivuuta + + + + Cancel outgoing call + Peruuta lähtevä puhelu + + + + Cancel + Peru + + + + Start video call + Aloita videopuhelu + + + + Start audio call + Aloita äänipuhelu + + + + Clear conversation + Tyhjennä keskustelu + + + + Remove contact + Poista yhteystieto + + + + Block contact + Estä yhteystieto + + + + Copy number + Kopioi numero + + + + Search your received invitations + Hae vastaanotetuista kutsuista + + + + Contact me on Jami + Ota minuun yhteyttä Jamilla + + + + My Id is : + Minun id on : + + + + %1 + %1 is the contact username + %1 + + + + %1 + %1 is the contact unique identifier + %1 + + + + Call incoming from %1 + Saapuva puhelu %1 + + + + DeleteAccountDialog + + + Account deletion + Tunnuksen poisto + + + + Do you really want to delete the following account? + Haluatko todella poistaa seuraavan tunnuksen? + + + + If this account hasn't been exported, or added to another device, it will be irrevocably lost. + Jos tätä tunnusta ei ole viety tai lisätty toiseen laitteeseen, se katoaa lopullisesti. + + + + Permanently delete account + Poista tunnus pysyvästi + + + + Delete + Poista + + + + Cancel account deletion + Peruuta tunnuksen poisto + + + + Cancel + Peru + + + + DeviceItemWidget + + + Form + Muoto + + + + Device Id + Laitteen Id + + + + this device + tämä laite + + + + InviteButtonsWidget + + + Accept + Hyväksy + + + + Refuse + Kieltäydy + + + + Block + Estä + + + + LinkDeviceDialog + + + Dialog + Valintaikkuna + + + + Enter your account password + Anna tunnuksen salasana + + + + Password + Salasana + + + + Ok + Vahvista + + + + Cancel + Peruuta + + + + Exporting account + Tunnuksen vienti + + + + Your PIN is + Sinun PIN on + + + + PIN + PIN + + + + This pin and the account password should be entered in your device within 10 minutes. + Tämä pin-koodi ja tunnuksen salasana on syötettävä laitteeseesi 10 minuutin kuluessa. + + + + Close + Sulje + + + + Link Another Device + Linkitä toinen laite + + + + Incorrect password + Väärä salasana + + + + Something went wrong. +Please try again later. + Jokin meni pieleen. +Yritä myöhemmin uudelleen. + + + + MainWindow + + + Settings + Asetukset + + + + Exit + Poistu + + + + About + Tietoa + + + + Jami + Jami + + + + NameRegistrationDialog + + + Set Registered Name + Aseta rekisteröity nimi + + + + Enter your account password + Anna tunnuksen salasana + + + + Password text input + Salasana tekstinsyöttö + + + + Password text entry + Salasanan tekstikenttä + + + + Password + Salasana + + + + Register + Rekistöröi + + + + Cancel + Peruuta + + + + Registering Name + Rekisteröidään nimeä + + + + Something went wrong + Jokin meni pieleen. + + + + Close + Sulje + + + + Incorrect password + Väärä salasana + + + + Network error + Verkkovirhe + + + + NewWizardWidget + + + Form + Muoto + + + + Welcome Label + Tervehdysmerkki + + + + Welcome to + Tervetuloa + + + + Welcome Logo + Tervetuloa logo + + + + Create Jami account button + Luo Jami-tunnuksen painike + + + + Push button for Jami account creation start trigger + Paina painiketta Jami-tunnuksen luomiseksi + + + + Create a Jami account + Luo Jami-tunnus + + + + Link device button + Linkitä laite painike + + + + Push button for device linkage start trigger + Paina painiketta laitteen linkittämiseksi + + + + Link this device to an account + Yhdistä tämä laite tunnukseen + + + + Create Jami SIP account button + Luo Jami SIP-tunnuksen painike + + + + Push button for Jami SIP account creation start trigger + Paina painiketta Jami SIP-tunnuksen luomiseksi + + + + Create a SIP account + Luo SIP tunnus + + + + Link this device to an existing account + Yhdistä tämä laite olemassa olevaan tunnukseen + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Ubuntu'; font-size:14px; color:#555555;">To link this device to another account, you first </span><span style=" font-family:'Ubuntu'; font-size:14px; font-weight:600; color:#555555;">need to obtain a PIN</span><span style=" font-family:'Ubuntu'; font-size:14px; color:#555555;"> code. To generate the PIN code:</span></p> +<ol style="margin-top: 0px; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; -qt-list-indent: 1;"><li style=" font-family:'Ubuntu'; font-size:14px; color:#555555;" style=" margin-top:12px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:14px;">Go to the </span><span style=" font-size:14px; font-weight:600;">Account management setting</span><span style=" font-size:14px;"> of a previous device</span></li> +<li style=" font-family:'Ubuntu'; font-size:14px; color:#555555;" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:14px;">Choose the </span><span style=" font-size:14px; font-weight:600;">Jami account</span><span style=" font-size:14px;"> you want to use</span></li> +<li style=" font-family:'Ubuntu'; font-size:14px; color:#555555;" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:14px;">Go to the </span><span style=" font-size:14px; font-weight:600;">Devices</span><span style=" font-size:14px;"> tab</span></li> +<li style=" font-family:'Ubuntu'; font-size:14px; color:#555555;" style=" margin-top:0px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:14px;">Select </span><span style=" font-size:14px; font-weight:600;">Add a device</span></li></ol> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Ubuntu'; font-size:14px; color:#555555;">You will get the necessary PIN to complete this form. The PIN is only valid for </span><span style=" font-family:'Ubuntu'; font-size:14px; font-weight:600; color:#555555;">10 minutes</span><span style=" font-family:'Ubuntu'; font-size:10px; color:#555555;">.</span></p></body></html> + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Ubuntu'; font-size:14px; color:#555555;">Jos haluat linkittää tämän laitteen toiseen tunnukseen, sinun on </span><span style=" font-family:'Ubuntu'; font-size:14px; font-weight:600; color:#555555;">ensin hankittava PIN</span><span style=" font-family:'Ubuntu'; font-size:14px; color:#555555;"> -koodi. PIN-koodin luominen:</span></p> +<ol style="margin-top: 0px; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; -qt-list-indent: 1;"><li style=" font-family:'Ubuntu'; font-size:14px; color:#555555;" style=" margin-top:12px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:14px;">Mene </span><span style=" font-size:14px; font-weight:600;">käyttäjäasetuksiin</span><span style=" font-size:14px;"> aiemmasta laitteesta.</span></li> +<li style=" font-family:'Ubuntu'; font-size:14px; color:#555555;" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:14px;">Valitse </span><span style=" font-size:14px; font-weight:600;">Jami-tunnus</span><span style=" font-size:14px;"> jota haluat käyttää</span></li> +<li style=" font-family:'Ubuntu'; font-size:14px; color:#555555;" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:14px;">Mene </span><span style=" font-size:14px; font-weight:600;">Laitteet</span><span style=" font-size:14px;"> välilehteen</span></li> +<li style=" font-family:'Ubuntu'; font-size:14px; color:#555555;" style=" margin-top:0px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:14px;">Valitse </span><span style=" font-size:14px; font-weight:600;">Lisää laite</span></li></ol> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Ubuntu'; font-size:14px; color:#555555;">Saat tarvittavan PIN-koodin tämän lomakkeen lopussa. PIN-koodi on voimassa vain </span><span style=" font-family:'Ubuntu'; font-size:14px; font-weight:600; color:#555555;">10 minuuttia</span><span style=" font-family:'Ubuntu'; font-size:10px; color:#555555;">.</span></p></body></html> + + + + Enter your pin: + Syötä pin-koodisi: + + + + Or import a file: + Tai tuo tiedosto: + + + + Link from exported account archive file + Linkki viedystä tunnuksen arkistotiedostosta + + + + + + (None) + (Ei mitään) + + + + Password: + Salasana: + + + + + Profile + Profiili + + + + + Profile name + Profiilin nimi + + + + Account + Tunnus + + + + Register your username. +This will reserve the username so that only you can use it. +Your friends will be able to call you with your usename +instead of using your ID. + Rekisteröi käyttäjänimesi. +Tämä varaa käyttäjätunnuksen, jotta vain sinä voit käyttää sitä. +Kaverisi voivat soittaa sinulle käyttäjänimelläsi sen sijaan, +että käyttäisit tunnustasi. + + + + Public username checkbox + Julkinen käyttäjänimi valintaruutu + + + + Checkbox selecting if the user wants a public username + Merkitse laatikko, jos käyttäjä haluaa julkisen käyttänimen + + + + Register public username + Rekisteröi julkinen käyttäjänimi + + + + Public username edit + Julkisen käyttäjänimen muokkaus + + + + Choose your username + Valitse käyttäjänimesi + + + + Password text input + Salasana tekstinsyöttö + + + + Password text entry + Salasanan tekstikenttä + + + + + Password + Salasana + + + + + Password confirmation text input + Salasanan vahvistuksen tekstikenttä + + + + Confirm password + Varmista salasana + + + + SIP Account + SIP tunnus + + + + SIP Server edit + SIP-palvelimen muokkaus + + + + Server + Palvelin + + + + SIP proxy input + Syötä SIP-välityspalvelin + + + + SIP proxy text entry + SIP-välityspalvelimen tekstikenttä + + + + Proxy + Välityspalvelin + + + + SIP username input + Syötä SIP-käyttäjänimi + + + + SIP Password text entry + SIP-salasanan tekstikenttä + + + + Username + Käyttäjänimi + + + + + SIP Password text input + Syötä SIP-salasana + + + + Generating your Jami account… + Luodaan Jami-tunnusta... + + + + Previous page button + Edellinen sivu -painike + + + + push button to access previous page of wizard + paina painiketta päästäksesi ohjatun toiminnon edelliselle sivulle + + + + Previous + Edellinen + + + + Cancel account create/link + Peruuta tunnuksen luominen/linkitys + + + + push button to cancel account creation or linking + painamalla painiketta voit peruuttaa tunnuksen luomisen tai linkittämisen + + + + Back + Takaisin + + + + Next page Button + Seuraava sivu -painike + + + + Push button to access next page of wizard + Painamalla painiketta pääset ohjatun toiminnon seuraavalle sivulle + + + + Next + Seuraava + + + + Open File + Avaa tiedosto + + + + Jami archive files (*.gz); All files (*) + Jami-arkistoidut tiedostot (*.gz); Kaikki tiedostot (*) + + + + Your account needs to be migrated. Enter your password. + Tunnuksesi on siirrettävä. Syötä salasanasi. + + + + Migrating your Jami account... + Jami-tunnuksesi siirretään… + + + + Importing account archive... + Tuodaan Tunnus-arkistoa... + + + + Generating your Jami account... + Luodaan sinun Jami-tunnusta... + + + + Generating your SIP account... + Luodaan sinun SIP-tunnusta... + + + + Error creating account + Virhe tunnuksen luomisessa + + + + PasswordDialog + + + Change Account Password + Vaihda tunnuksen salasana + + + + Enter Current Password + Anna nykyinen salasana + + + + Enter New Password + Anna uusi salasana + + + + Confirm New Password + Vahvista uusi salasana + + + + Confirm + Vahvista + + + + Cancel + Peruuta + + + + Current Password Incorrect + Nykyinen salasana väärä + + + + PhotoBoothDialog + + + Photobooth + Valokuva-automaatti + + + + PhotoboothWidget + + + Form + Muoto + + + + Photobooth display + Valokuvanäyttö + + + + Choose File + Valitse tiedosto + + + + Image Files (*.jpg *.jpeg *.png) + Kuvatiedostot (*.jpg *.jpeg *.png) + + + + PrivateBridging + + + Choose File + Valitse tiedosto + + + + Files (*) + Tiedostot (*) + + + + QObject + + + No default mail client found + Oletussähköpostiohjelmaa ei löytynyt + + + + + Edit Device Name + Muokkaa laitteen nimeä + + + + Unlink Device From Account + Irrota laite tunnuksesta + + + + Save new device name + Tallenna uuden laitteen nimi + + + + Add as contact + Lisää yhteystietona + + + + RingButton + + + Select folder + Valitse kansio + + + + SettingsWidget + + + Form + Muoto + + + + Settings + Asetukset + + + + Account + Tunnus + + + + + General + Yleiset + + + + + Audio / Video + Ääni / Video + + + + System + Järjestelmä + + + + Enable desktop notifications + Työpöytäilmoitukset käyttöön + + + + Keep minimized on close + Pidä pienennettynä suljettaessa + + + + Download folder + Ladatut kansio + + + + Save in + Tallenna sisään + + + + Always Recording + Tallentaa aina + + + + Updates + Päivitykset + + + + Check for updates automatically every + Tarkista päivitykset automaattisesti joka + + + + Interval between update checks in days selector + Päivitystarkistusten välinen aika + + + + days + päivää + + + + Check for updates now button + Tarkista päivitykset nyt -painike + + + + Check for updates now + Tarkista päivitykset nyt + + + + Password + Salasana + + + + + Enable + Päällä + + + + toggle enable notifications + Vaihda ilmoitukset käyttöön + + + + Toggle keep minimized on close + Valinta pidä pinennettynä suljettaessa + + + + Call Recordings + Puhelun tallenteet + + + + Toggle automatic updates + Vaihda automaattiset päivitykset + + + + Jami Account + Jami tunnus + + + + + Profile + Profiili + + + + + Identity + Tunnistetiedot + + + + Id + Id + + + + Registered name + Rekisteröity nimi + + + + Type here to register a username + Kirjoita tähän rekisteröidäksesi käyttäjänimen + + + + Register + Rekistöröi + + + + Change Password + Vaihda salasana + + + + Export Account + Vie tunnus + + + + + Delete Account + Poista tunnus + + + + Linked Devices + Linkitetyt laitteet + + + + Link Another Device + Linkitä toinen laite + + + + Banned Contacts + Estetyt yhteystiedot + + + + Format + Muoto + + + + Video device framerate selector + Videolaitteen kuvanopeuden valitsin + + + + Preview unavailable + Esikatselua ei käytettävissä + + + + + Advanced Account Settings + Tilin lisäasetukset + + + + SIP Account + SIP tunnus + + + + Username + Käyttäjänimi + + + + Hostname + Yhteysosoite + + + + Proxy + Välityspalvelin + + + + Audio + Ääni + + + + Microphone + Mikrofoni + + + + Audio input device selector + Äänen sisääntulon valitsin + + + + Output Device + Ulostulon laite + + + + Choose the output device + Valitse laitteen ulostulo + + + + Video + Video + + + + Device + Laite + + + + Video device selector + Videolaitteen valitsin + + + + A registered name should not have any spaces and must be at least three letters long + Rekisteröitävässä nimessä ei saa olla välilyöntejä ja sen on oltava vähintään kolme kirjainta pitkä + + + + This name is already taken + Tämä nimi on jo varattu + + + + + Enter an alias + Anna lempinimi + + + + Register this name + Rekisteröi tämä nimi + + + + Remove Device + Poista laite + + + + Enter this account's password to confirm the removal of this device + Anna tämän tunnuksen salasana vahvistaaksesi laitteen poistamisen + + + + Are you sure you wish to remove this device? + Haluatko varmasti poistaa tämän laitteen? + + + + Export Account Here + Vie tunnus tähän + + + + Select A Folder For Your Downloads + Valitse kansio latauksia varten + + + + Select A Folder For Your Recordings + Valitse kansio tallennuksia varten + + + + VideoOverlay + + + Call on Hold + Puhelu pidossa + + + + Hold / Unhold + Pitoon / poista pidosta + + + + Chat + keskustelu + + + + Mute Mic + Mykistä mikki + + + + Record call + Tallenna puhelu + + + + Name label + Nimikenttä + + + + Time elapsed + Kulunut aika + + + + 00:00 + 00:00 + + + + Hangup + Katkaisu + + + + Mute Video + Mykistä video + + + + VideoView + + + Share entire screen + Jaa näyttö + + + + Share screen area + Jaa osa näytöstä + + + + Share file + Jaa tiedosto + + + \ No newline at end of file diff --git a/translations/ring_client_windows_fr.ts b/translations/ring_client_windows_fr.ts new file mode 100644 index 00000000..a3fd61b0 --- /dev/null +++ b/translations/ring_client_windows_fr.ts @@ -0,0 +1,1600 @@ + + + AboutDialog + + + + About + À Propos + + + + about button + Le bouton à-propos + + + + credits button + Bouton de crédits + + + + Credits + Crédits + + + + Free as in Freedom + Free as in Freedom + + + + The Microsoft Windows client for Jami. +Jami is a secured and distributed communication software. + Le client Windows de Jami +Jami est un logiciel libre de communication sécurisé et distribué. + + + + version + version + + + + Created by: + Créé par : + + + + Artwork by: + Graphismes par : + + + + Based on the SFLPhone project + Basé sur le projet SFLphone + + + + AccountItemDelegate + + + Add Account + Ajouter un compte + + + + AdvancedSIPSettingsWidget + + + Form + Formulaire + + + + Call Settings + Paramètres des Appels + + + + Auto Answer Calls + Répondre automatiquement les appels + + + + Enable Custom Ringtone + Activer les sonneries personnalisables + + + + Connectivity + Connectivité + + + + STUN Address + Adresse STUN + + + + Use STUN + Utiliser STUN + + + + Use UPnP + Utiliser UPnP + + + + Use TURN + Utiliser TURN + + + + TURN Password + Mot de passe TURN + + + + TURN Username + Nom d'utilisateur TURN + + + + TURN Address + Adresse du serveur TURN + + + + Media + Médias + + + + Enable Video + Activer la vidéo + + + + Video Codecs + Codecs vidéo + + + + Audio Codecs + Codecs audio + + + + Audio Files (*.wav *.ogg *.opus *.mp3 *aiff *wma) + Fichiers audio ( wav, ogg, opus, mp3, aiff, wma) + + + + Add a custom ringtone + Ajouter une sonnerie externe + + + + AdvancedSettingsWidget + + + Form + Formulaire + + + + Call Settings + Paramètres des Appels + + + + Allow Calls From Untrusted Peers + Accepter les appels provenant de peers non fiables + + + + Auto Answer Calls + Répondre automatiquement les appels + + + + Enable Custom Ringtone + Activer les sonneries personnalisables + + + + Add a custom ringtone + Ajouter une sonnerie externe + + + + Name Server + Nom du Serveur + + + + Address + Adresse + + + + OpenDHT Configuration + Configuration OpenDHT + + + + Enable Proxy + Utiliser un nœud délégataire + + + + Bootstrap + Adresse du nœud d'amorçage + + + + Security + Sécurité + + + + Private Key Password + Mot de passe de la clé + + + + User Certificate + Certificat de l'utilisateur + + + + Private Key + Clé privée + + + + CA Certificate + Certificat CA + + + + Connectivity + Connectivité + + + + Use STUN + Utiliser STUN + + + + STUN Address + Adresse STUN + + + + Use UPnP + Utiliser UPnP + + + + Use TURN + Utiliser TURN + + + + TURN Password + Mot de passe TURN + + + + TURN Username + Nom d'utilisateur TURN + + + + TURN Address + Adresse du serveur TURN + + + + Media + Médias + + + + Enable Video + Activer la vidéo + + + + Audio Codecs + Codecs audio + + + + Video Codecs + Codecs vidéo + + + + Audio Files (*.wav *.ogg *.opus *.mp3 *aiff *wma) + Fichiers audio ( wav, ogg, opus, mp3, aiff, wma) + + + + AnimatedOverlay + + + Form + Formulaire + + + + BannedItemWidget + + + Form + Formulaire + + + + name + nom + + + + id + id + + + + CallWidget + + + Show conversations + Montrer les conversations + + + + Conversations + Conversations + + + + Search contact text input + Rechercher le texte du contact + + + + Jami is free software for universal communication which respects the freedoms and privacy of its users. + Jami est un logiciel libre de communication universel qui respecte la vie privée et l'intimité de ses utilisateurs. + + + + + This is your ID. +Copy and share it with your friends! + + Ceci est votre identifiant Jami. Conservez et partagez-le avec vos amis ! + + + + Show ring ID QR code + Montrer le code QR d'identification ring + + + + Share ring ID button + Partager le bouton d'identification ring + + + + Double-click to copy + Double-cliquez pour copier + + + + Error while generating QR Code + Erreur pendant la génération du QR code + + + + + best name + meilleur nom + + + + best Id + Meilleur ID + + + + Back to homepage button + Bouton de retour a la page d'accueil + + + + Add to contacts + Ajouter aux contacts + + + + Show invites + Montrer les invitations + + + + Invites + Invitations + + + + + Find a new or existing contact + Recherche de contacts nouveaux ou existants + + + + Wants to talk to you! + souhaite entrer en communication ! + + + + Answer incoming call button + Bouton de réponse d'appel + + + + Ignore incoming call button + Bouton de refus d'appel + + + + Answer + Répondre + + + + Ignore + Ignorer + + + + Cancel outgoing call + Annuler l'appel sortant + + + + Cancel + Annuler + + + + Start video call + Démarrer un appel vidéo + + + + Start audio call + Démarrer un appel audio + + + + Clear conversation + Effacer la conversation + + + + Remove contact + Retirer le contact + + + + Block contact + Bloquer le contact + + + + Copy number + Copier le numéro ou identifiant Ring + + + + Search your received invitations + Rechercher dans les invitations reçues + + + + Contact me on Jami + Contactez moi sur Jami + + + + My Id is : + Mon ID est : + + + + %1 + %1 is the contact username + %1 + + + + %1 + %1 is the contact unique identifier + %1 + + + + Call incoming from %1 + Appel entrant de %1 + + + + DeleteAccountDialog + + + Account deletion + Suppression de compte + + + + Do you really want to delete the following account? + Souhaitez-vous vraiment supprimer ce compte ? + + + + If this account hasn't been exported, or added to another device, it will be irrevocably lost. + Si ce compte n'a pas été exporté, ou ajouté vers un autre appareil, il sera perdu irrémédiablement. + + + + Permanently delete account + Supprimer de manière définitive le compte + + + + Delete + Supprimer + + + + Cancel account deletion + Annuler la suppression du compte + + + + Cancel + Annuler + + + + DeviceItemWidget + + + Form + Formulaire + + + + Device Id + Identifiant d'appareil + + + + this device + cet appareil + + + + InviteButtonsWidget + + + Accept + Accepter + + + + Refuse + Refuser + + + + Block + Bloquer + + + + LinkDeviceDialog + + + Dialog + Dialogue + + + + Enter your account password + Entrer le mot de passe de votre compte + + + + Password + Mot de passe + + + + Ok + OK + + + + Cancel + Annuler + + + + Exporting account + Compte exporté + + + + Your PIN is + Votre NIP est + + + + PIN + NIP + + + + This pin and the account password should be entered in your device within 10 minutes. + Ce NIP ainsi que le mot de passe du compte doivent être saisis dans votre nouvel appareil dans les 10 prochaines minutes. + + + + Close + Fermer + + + + Link Another Device + Associer un autre appareil + + + + Incorrect password + Mot de passe incorrecte + + + + Something went wrong. +Please try again later. + Quelque chose s'est mal passée. +Veuillez réessayer plus tard. + + + + MainWindow + + + Settings + Paramètres + + + + Exit + Sortir + + + + About + À Propos + + + + Jami + Jami + + + + NameRegistrationDialog + + + Set Registered Name + Enregistrer un nom d'utilisateur + + + + Enter your account password + Entrer le mot de passe de votre compte + + + + Password text input + Saisie du mot de passe + + + + Password text entry + Saisie de mot de passe + + + + Password + Mot de passe + + + + Register + Enregistrer + + + + Cancel + Annuler + + + + Registering Name + En cours d’enregistrement du nom + + + + Something went wrong + Quelque chose s'est mal passée. + + + + Close + Fermer + + + + Incorrect password + Mot de passe incorrecte + + + + Network error + Erreur de réseau + + + + NewWizardWidget + + + Form + Formulaire + + + + Welcome Label + étiquette de bienvenue + + + + Welcome to + Bienvenue sur + + + + Welcome Logo + Logo d'accueil + + + + Create Jami account button + Bouton de création de compte Jami + + + + Push button for Jami account creation start trigger + Bouton pour déclencher la création d'un compte Ring + + + + Create a Jami account + Créer un compte Jami + + + + Link device button + Bouton pour lier le compte de l'appareil + + + + Push button for device linkage start trigger + Appuyez sur le bouton pour déclencher la liaison de l'appareil + + + + Link this device to an account + Lier cet appareil à un compte + + + + Create Jami SIP account button + Bouton de création de compte SIP Jami + + + + Push button for Jami SIP account creation start trigger + Bouton pour déclencher la création d'un compte Jami + + + + Create a SIP account + Créer un compte SIP + + + + Link this device to an existing account + Lier cet appareil à un compte existant + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Ubuntu'; font-size:14px; color:#555555;">To link this device to another account, you first </span><span style=" font-family:'Ubuntu'; font-size:14px; font-weight:600; color:#555555;">need to obtain a PIN</span><span style=" font-family:'Ubuntu'; font-size:14px; color:#555555;"> code. To generate the PIN code:</span></p> +<ol style="margin-top: 0px; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; -qt-list-indent: 1;"><li style=" font-family:'Ubuntu'; font-size:14px; color:#555555;" style=" margin-top:12px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:14px;">Go to the </span><span style=" font-size:14px; font-weight:600;">Account management setting</span><span style=" font-size:14px;"> of a previous device</span></li> +<li style=" font-family:'Ubuntu'; font-size:14px; color:#555555;" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:14px;">Choose the </span><span style=" font-size:14px; font-weight:600;">Jami account</span><span style=" font-size:14px;"> you want to use</span></li> +<li style=" font-family:'Ubuntu'; font-size:14px; color:#555555;" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:14px;">Go to the </span><span style=" font-size:14px; font-weight:600;">Devices</span><span style=" font-size:14px;"> tab</span></li> +<li style=" font-family:'Ubuntu'; font-size:14px; color:#555555;" style=" margin-top:0px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:14px;">Select </span><span style=" font-size:14px; font-weight:600;">Add a device</span></li></ol> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Ubuntu'; font-size:14px; color:#555555;">You will get the necessary PIN to complete this form. The PIN is only valid for </span><span style=" font-family:'Ubuntu'; font-size:14px; font-weight:600; color:#555555;">10 minutes</span><span style=" font-family:'Ubuntu'; font-size:10px; color:#555555;">.</span></p></body></html> + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Cantarell'; font-size:11pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Ubuntu'; font-size:12pt;">Pour associer cet appareil à un autre compte, vous devez d'abord obtenir un NIP</span>Pour cela, allez dans la gestion des comptes de l'appareil contenant le compte voulu et sélectionnez le compte que vous souhaitez utiliser. +<li style=" font-family:'Ubuntu'; font-size:12pt;" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Allez à la tabulation<span style=" font-weight:600;">Appareils</span></li> +<li style=" font-family:'Ubuntu'; font-size:12pt;" style=" margin-top:0px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Choisissez<span style=" font-weight:600;">Ajouter un appareil</span></li></ol> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Ubuntu'; font-size:12pt;">Vous obtiendrez alors un NIP qui vous permettra de terminer l'opération. Ce NIP est seulement valide pour une durée de </span><span style=" font-family:'Ubuntu'; font-size:12pt; font-weight:600;">10 minutes</span><span style=" font-family:'Ubuntu'; font-size:12pt;">.</span></p></body></html> + + + + Enter your pin: + Entrez votre NIP : + + + + Or import a file: + Ou importer une archive : + + + + Link from exported account archive file + Lier depuis une archive du compte exportée + + + + + + (None) + (None) + + + + Password: + Mot de passe : + + + + + Profile + Profil + + + + + Profile name + Nom du profile + + + + Account + Compte + + + + Register your username. +This will reserve the username so that only you can use it. +Your friends will be able to call you with your usename +instead of using your ID. + Enregistre votre nom d'utilisateur Jami. +Ceci réserve ce nom de façon définitive et uniquement pour votre usage. +Vos amis pourront vous appeler avec ce nom. + + + + Public username checkbox + case à cocher nom d'utilisateur public + + + + Checkbox selecting if the user wants a public username + Case à cocher si l'utilisateur veut un identifiant public + + + + Register public username + Enregistrer un nom d'utilisateur public + + + + Public username edit + Modification de l'identifiant public + + + + Choose your username + Choisissez un nom d'utilisateur + + + + Password text input + Saisie du mot de passe + + + + Password text entry + Saisie de mot de passe + + + + + Password + Mot de passe + + + + + Password confirmation text input + Texte de confirmation de l'entrée du mot de passe + + + + Confirm password + Confirmer le mot de passe + + + + SIP Account + Compte SIP + + + + SIP Server edit + Adresse du serveur SIP + + + + Server + Serveur + + + + SIP proxy input + Adresse du proxy SIP + + + + SIP proxy text entry + Texte du proxy SIP + + + + Proxy + Serveur mandataire + + + + SIP username input + SIP du nom d'usager en entré + + + + SIP Password text entry + Texte de mot de passe du compte SIP + + + + Username + Nom d'utilisateur + + + + + SIP Password text input + Texte de mot de passe du compte SIP + + + + Generating your Jami account… + Génération de votre compte Jami... + + + + Previous page button + Bouton de la page précédente + + + + push button to access previous page of wizard + Appuyez sur le bouton pour accéder à la page précédente + + + + Previous + Précédent + + + + Cancel account create/link + Annuler la création/lien de compte + + + + push button to cancel account creation or linking + Bouton pour déclencher la création d'un compte Jami ou association + + + + Back + Précédent + + + + Next page Button + bouton prochaine page + + + + Push button to access next page of wizard + Appuyez sur le bouton pour accéder à la page suivante de l'assistant + + + + Next + Suivant + + + + Open File + Ouvrir un fichier + + + + Jami archive files (*.gz); All files (*) + Fichier d'archive de compte Jami (*.gz); Tout fichier (*) + + + + Your account needs to be migrated. Enter your password. + Votre compte doit être migré. Entrez votre mot de passe + + + + Migrating your Jami account... + Migration de votre compte Jami... + + + + Importing account archive... + Importation de l'archive du compte + + + + Generating your Jami account... + Génération de votre compte Jami... + + + + Generating your SIP account... + Création de votre compte SIP ... + + + + Error creating account + Erreur pendant la création du compte + + + + PasswordDialog + + + Change Account Password + Changer le mot de passe du compte + + + + Enter Current Password + Entrez le mot de passe actuel + + + + Enter New Password + Entrez le nouveau mot de passe + + + + Confirm New Password + Confirmer le nouveau mot de passe + + + + Confirm + Confirmer + + + + Cancel + Annuler + + + + Current Password Incorrect + Mot de passe actuel incorrect + + + + PhotoBoothDialog + + + Photobooth + Kiosque de photo + + + + PhotoboothWidget + + + Form + Formulaire + + + + Photobooth display + Affichage du photomaton + + + + Choose File + Choisir un fichier + + + + Image Files (*.jpg *.jpeg *.png) + Fichiers images (JPG, JPEG, PNG) + + + + PrivateBridging + + + Choose File + Choisir un fichier + + + + Files (*) + Fichiers (*) + + + + QObject + + + No default mail client found + Aucun client email trouvé + + + + + Edit Device Name + Modifier le nom de l'appareil + + + + Unlink Device From Account + Dissocier cet appareil d'un compte + + + + Save new device name + Sauvegarder le nouveau nom d'appareil + + + + Add as contact + Rajouter comme contact + + + + RingButton + + + Select folder + Selectionner le fichier + + + + SettingsWidget + + + Form + Formulaire + + + + Settings + Paramètres + + + + Account + Compte + + + + + General + Général + + + + + Audio / Video + Audio / Vidéo + + + + System + Système + + + + Enable desktop notifications + Activer les notifications du bureau + + + + Keep minimized on close + Laisser minimisé en fermant + + + + Download folder + Répertoire de téléchargement + + + + Save in + Enregistrer dans + + + + Always Recording + Enregistrer tout le temps + + + + Updates + Mises à jour + + + + Check for updates automatically every + Vérifiez automatiquement les mises à jours tous les + + + + Interval between update checks in days selector + Sélectionneur d'intervalle de jour pour la vérification des mises à jour + + + + days + jours + + + + Check for updates now button + Bouton vérifier les mises à jour actuelles + + + + Check for updates now + Vérifier les mises-à-jour + + + + Password + Mot de passe + + + + + Enable + Activer + + + + toggle enable notifications + Case à cocher Activer les notifications + + + + Toggle keep minimized on close + Case à cocher laisser minimisé à la fermeture + + + + Call Recordings + Appel enregistrement + + + + Toggle automatic updates + Case à cocher des mises à jour automatiques + + + + Jami Account + Compte Jami + + + + + Profile + Profil + + + + + Identity + Identité + + + + Id + Identifiant + + + + Registered name + Nom enregistré + + + + Type here to register a username + Saisissez ici le nom d'enregistrement + + + + Register + Enregistrer + + + + Change Password + Changer le mot de passe + + + + Export Account + Exporter le compte + + + + + Delete Account + Supprimer le compte + + + + Linked Devices + Appareils associés + + + + Link Another Device + Associer un autre appareil + + + + Banned Contacts + Contacts bannis + + + + Format + Format + + + + Video device framerate selector + Sélecteur du débit de trame vidéo + + + + Preview unavailable + Prévisualisation indisponible + + + + + Advanced Account Settings + Paramètres avancés du compte + + + + SIP Account + Compte SIP + + + + Username + Nom d'utilisateur + + + + Hostname + Nom d'hôte + + + + Proxy + Serveur mandataire + + + + Audio + Audio + + + + Microphone + Microphone + + + + Audio input device selector + Sélecteur d'entrée audio + + + + Output Device + Périphérique de sortie + + + + Choose the output device + Choisissez le périphérique de sortie + + + + Video + Vidéo + + + + Device + Appareil + + + + Video device selector + Sélecteur de périphérique vidéeo + + + + A registered name should not have any spaces and must be at least three letters long + Un nom d’enregistrement est composé d'un minimum de 3 caractères et ne doit contenir aucun espace + + + + This name is already taken + Ce nom a déjà été pris + + + + + Enter an alias + Entrer un alias + + + + Register this name + Enregistrer ce nom + + + + Remove Device + Supprimer cet appareil + + + + Enter this account's password to confirm the removal of this device + Entrer le mot de passe du compte pour confirmer la suppression de cet appareil + + + + Are you sure you wish to remove this device? + Êtes-vous certain que vous souhaitez supprimer cet appareil ? + + + + Export Account Here + Exporter le compte ici + + + + Select A Folder For Your Downloads + Choisissez un répertoire pour vos téléchargements + + + + Select A Folder For Your Recordings + Choisissez un répertoire pour vos enregistrements + + + + VideoOverlay + + + Call on Hold + Appel en attente + + + + Hold / Unhold + Pause / Reprendre + + + + Chat + Clavardage + + + + Mute Mic + Couper le micro + + + + Record call + Enregistrer l'appel + + + + Name label + Étiquette de nom + + + + Time elapsed + Temps écoulé + + + + 00:00 + 00:00 + + + + Hangup + Raccrocher + + + + Mute Video + Désactiver la vidéo + + + + VideoView + + + Share entire screen + Partager tout l'écran + + + + Share screen area + Partager une partie de l'écran + + + + Share file + Partager un fichier + + + \ No newline at end of file diff --git a/translations/ring_client_windows_fr_BE.ts b/translations/ring_client_windows_fr_BE.ts new file mode 100644 index 00000000..f94c3862 --- /dev/null +++ b/translations/ring_client_windows_fr_BE.ts @@ -0,0 +1,1589 @@ + + + AboutDialog + + + + About + + + + + about button + + + + + credits button + + + + + Credits + + + + + Free as in Freedom + + + + + The Microsoft Windows client for Jami. +Jami is a secured and distributed communication software. + + + + + version + + + + + Created by: + + + + + Artwork by: + + + + + Based on the SFLPhone project + + + + + AccountItemDelegate + + + Add Account + + + + + AdvancedSIPSettingsWidget + + + Form + + + + + Call Settings + + + + + Auto Answer Calls + + + + + Enable Custom Ringtone + + + + + Connectivity + Connectivité + + + + STUN Address + + + + + Use STUN + Utiliser STUN + + + + Use UPnP + + + + + Use TURN + Utiliser le TURN + + + + TURN Password + + + + + TURN Username + + + + + TURN Address + + + + + Media + + + + + Enable Video + + + + + Video Codecs + + + + + Audio Codecs + + + + + Audio Files (*.wav *.ogg *.opus *.mp3 *aiff *wma) + + + + + Add a custom ringtone + + + + + AdvancedSettingsWidget + + + Form + + + + + Call Settings + + + + + Allow Calls From Untrusted Peers + + + + + Auto Answer Calls + + + + + Enable Custom Ringtone + + + + + Add a custom ringtone + + + + + Name Server + + + + + Address + Adresse + + + + OpenDHT Configuration + + + + + Enable Proxy + + + + + Bootstrap + Amorcer + + + + Security + Sécurité + + + + Private Key Password + + + + + User Certificate + + + + + Private Key + + + + + CA Certificate + + + + + Connectivity + Connectivité + + + + Use STUN + Utiliser STUN + + + + STUN Address + + + + + Use UPnP + + + + + Use TURN + Utiliser le TURN + + + + TURN Password + + + + + TURN Username + + + + + TURN Address + + + + + Media + + + + + Enable Video + + + + + Audio Codecs + + + + + Video Codecs + + + + + Audio Files (*.wav *.ogg *.opus *.mp3 *aiff *wma) + + + + + AnimatedOverlay + + + Form + + + + + BannedItemWidget + + + Form + + + + + name + + + + + id + + + + + CallWidget + + + Show conversations + + + + + Conversations + Conversations + + + + Search contact text input + + + + + Jami is free software for universal communication which respects the freedoms and privacy of its users. + Jami est un logiciel libre de communication universel qui respecte la vie privée et l'intimité de ses utilisateurs. + + + + + This is your ID. +Copy and share it with your friends! + + + + + + Show ring ID QR code + + + + + Share ring ID button + + + + + Double-click to copy + + + + + Error while generating QR Code + + + + + + best name + + + + + best Id + + + + + Back to homepage button + + + + + Add to contacts + Ajouter aux contacts + + + + Show invites + + + + + Invites + + + + + + Find a new or existing contact + + + + + Wants to talk to you! + + + + + Answer incoming call button + + + + + Ignore incoming call button + + + + + Answer + + + + + Ignore + + + + + Cancel outgoing call + + + + + Cancel + Annuler + + + + Start video call + Démarrer appel video + + + + Start audio call + Démarrer appel audio + + + + Clear conversation + Effacer la conversation + + + + Remove contact + + + + + Block contact + Bloquer le contact + + + + Copy number + + + + + Search your received invitations + + + + + Contact me on Jami + + + + + My Id is : + + + + + %1 + %1 is the contact username + + + + + %1 + %1 is the contact unique identifier + + + + + Call incoming from %1 + + + + + DeleteAccountDialog + + + Account deletion + + + + + Do you really want to delete the following account? + + + + + If this account hasn't been exported, or added to another device, it will be irrevocably lost. + + + + + Permanently delete account + + + + + Delete + + + + + Cancel account deletion + + + + + Cancel + Annuler + + + + DeviceItemWidget + + + Form + + + + + Device Id + + + + + this device + + + + + InviteButtonsWidget + + + Accept + Accepter + + + + Refuse + Refuser + + + + Block + + + + + LinkDeviceDialog + + + Dialog + + + + + Enter your account password + + + + + Password + + + + + Ok + OK + + + + Cancel + Annuler + + + + Exporting account + + + + + Your PIN is + + + + + PIN + + + + + This pin and the account password should be entered in your device within 10 minutes. + + + + + Close + + + + + Link Another Device + + + + + Incorrect password + + + + + Something went wrong. +Please try again later. + + + + + MainWindow + + + Settings + + + + + Exit + + + + + About + + + + + Jami + Jami + + + + NameRegistrationDialog + + + Set Registered Name + + + + + Enter your account password + + + + + Password text input + + + + + Password text entry + + + + + Password + + + + + Register + Enregistrer + + + + Cancel + Annuler + + + + Registering Name + + + + + Something went wrong + + + + + Close + + + + + Incorrect password + + + + + Network error + + + + + NewWizardWidget + + + Form + + + + + Welcome Label + + + + + Welcome to + + + + + Welcome Logo + + + + + Create Jami account button + + + + + Push button for Jami account creation start trigger + + + + + Create a Jami account + Créer un compte Jami + + + + Link device button + + + + + Push button for device linkage start trigger + + + + + Link this device to an account + Lier cet appareil à un compte + + + + Create Jami SIP account button + + + + + Push button for Jami SIP account creation start trigger + + + + + Create a SIP account + + + + + Link this device to an existing account + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Ubuntu'; font-size:14px; color:#555555;">To link this device to another account, you first </span><span style=" font-family:'Ubuntu'; font-size:14px; font-weight:600; color:#555555;">need to obtain a PIN</span><span style=" font-family:'Ubuntu'; font-size:14px; color:#555555;"> code. To generate the PIN code:</span></p> +<ol style="margin-top: 0px; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; -qt-list-indent: 1;"><li style=" font-family:'Ubuntu'; font-size:14px; color:#555555;" style=" margin-top:12px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:14px;">Go to the </span><span style=" font-size:14px; font-weight:600;">Account management setting</span><span style=" font-size:14px;"> of a previous device</span></li> +<li style=" font-family:'Ubuntu'; font-size:14px; color:#555555;" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:14px;">Choose the </span><span style=" font-size:14px; font-weight:600;">Jami account</span><span style=" font-size:14px;"> you want to use</span></li> +<li style=" font-family:'Ubuntu'; font-size:14px; color:#555555;" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:14px;">Go to the </span><span style=" font-size:14px; font-weight:600;">Devices</span><span style=" font-size:14px;"> tab</span></li> +<li style=" font-family:'Ubuntu'; font-size:14px; color:#555555;" style=" margin-top:0px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:14px;">Select </span><span style=" font-size:14px; font-weight:600;">Add a device</span></li></ol> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Ubuntu'; font-size:14px; color:#555555;">You will get the necessary PIN to complete this form. The PIN is only valid for </span><span style=" font-family:'Ubuntu'; font-size:14px; font-weight:600; color:#555555;">10 minutes</span><span style=" font-family:'Ubuntu'; font-size:10px; color:#555555;">.</span></p></body></html> + + + + + Enter your pin: + + + + + Or import a file: + + + + + Link from exported account archive file + + + + + + + (None) + + + + + Password: + Mot de passe: + + + + + Profile + Profil + + + + + Profile name + + + + + Account + Compte + + + + Register your username. +This will reserve the username so that only you can use it. +Your friends will be able to call you with your usename +instead of using your ID. + + + + + Public username checkbox + + + + + Checkbox selecting if the user wants a public username + + + + + Register public username + Enregistrer un nom d'utilisateur public + + + + Public username edit + + + + + Choose your username + + + + + Password text input + + + + + Password text entry + + + + + + Password + + + + + + Password confirmation text input + + + + + Confirm password + + + + + SIP Account + + + + + SIP Server edit + + + + + Server + + + + + SIP proxy input + + + + + SIP proxy text entry + + + + + Proxy + + + + + SIP username input + + + + + SIP Password text entry + + + + + Username + + + + + + SIP Password text input + + + + + Generating your Jami account… + + + + + Previous page button + + + + + push button to access previous page of wizard + + + + + Previous + + + + + Cancel account create/link + + + + + push button to cancel account creation or linking + + + + + Back + + + + + Next page Button + + + + + Push button to access next page of wizard + + + + + Next + Suivant + + + + Open File + + + + + Jami archive files (*.gz); All files (*) + + + + + Your account needs to be migrated. Enter your password. + + + + + Migrating your Jami account... + + + + + Importing account archive... + + + + + Generating your Jami account... + + + + + Generating your SIP account... + + + + + Error creating account + + + + + PasswordDialog + + + Change Account Password + + + + + Enter Current Password + + + + + Enter New Password + + + + + Confirm New Password + + + + + Confirm + + + + + Cancel + Annuler + + + + Current Password Incorrect + + + + + PhotoBoothDialog + + + Photobooth + + + + + PhotoboothWidget + + + Form + + + + + Photobooth display + + + + + Choose File + + + + + Image Files (*.jpg *.jpeg *.png) + + + + + PrivateBridging + + + Choose File + + + + + Files (*) + + + + + QObject + + + No default mail client found + + + + + + Edit Device Name + + + + + Unlink Device From Account + + + + + Save new device name + + + + + Add as contact + + + + + RingButton + + + Select folder + + + + + SettingsWidget + + + Form + + + + + Settings + + + + + Account + Compte + + + + + General + Général + + + + + Audio / Video + + + + + System + + + + + Enable desktop notifications + + + + + Keep minimized on close + + + + + Download folder + + + + + Save in + + + + + Always Recording + + + + + Updates + + + + + Check for updates automatically every + + + + + Interval between update checks in days selector + + + + + days + + + + + Check for updates now button + + + + + Check for updates now + + + + + Password + + + + + + Enable + Activé + + + + toggle enable notifications + + + + + Toggle keep minimized on close + + + + + Call Recordings + + + + + Toggle automatic updates + + + + + Jami Account + + + + + + Profile + Profil + + + + + Identity + + + + + Id + + + + + Registered name + + + + + Type here to register a username + + + + + Register + Enregistrer + + + + Change Password + + + + + Export Account + Sauvegarder Compte + + + + + Delete Account + + + + + Linked Devices + + + + + Link Another Device + + + + + Banned Contacts + Contacts bannis + + + + Format + + + + + Video device framerate selector + + + + + Preview unavailable + + + + + + Advanced Account Settings + + + + + SIP Account + + + + + Username + + + + + Hostname + + + + + Proxy + + + + + Audio + Audio + + + + Microphone + + + + + Audio input device selector + + + + + Output Device + + + + + Choose the output device + + + + + Video + Vidéo + + + + Device + + + + + Video device selector + + + + + A registered name should not have any spaces and must be at least three letters long + + + + + This name is already taken + + + + + + Enter an alias + + + + + Register this name + + + + + Remove Device + + + + + Enter this account's password to confirm the removal of this device + + + + + Are you sure you wish to remove this device? + + + + + Export Account Here + + + + + Select A Folder For Your Downloads + + + + + Select A Folder For Your Recordings + + + + + VideoOverlay + + + Call on Hold + + + + + Hold / Unhold + + + + + Chat + + + + + Mute Mic + + + + + Record call + + + + + Name label + + + + + Time elapsed + + + + + 00:00 + + + + + Hangup + + + + + Mute Video + + + + + VideoView + + + Share entire screen + + + + + Share screen area + + + + + Share file + + + + \ No newline at end of file diff --git a/translations/ring_client_windows_fr_CA.ts b/translations/ring_client_windows_fr_CA.ts new file mode 100644 index 00000000..10e8ad74 --- /dev/null +++ b/translations/ring_client_windows_fr_CA.ts @@ -0,0 +1,1591 @@ + + + AboutDialog + + + + About + À propos + + + + about button + bouton à propos + + + + credits button + bouton crédits + + + + Credits + Crédits + + + + Free as in Freedom + + + + + The Microsoft Windows client for Jami. +Jami is a secured and distributed communication software. + Le client Microsoft Windows pour Jami. +Jami est un logiciel de communication sécurisé et distribué. + + + + version + version + + + + Created by: + Créé par : + + + + Artwork by: + Artwork de: + + + + Based on the SFLPhone project + Basé sur le projet SFLPhone + + + + AccountItemDelegate + + + Add Account + Ajouter un compte + + + + AdvancedSIPSettingsWidget + + + Form + Formulaire + + + + Call Settings + Paramètres d'appel + + + + Auto Answer Calls + Réponse automatique aux appels + + + + Enable Custom Ringtone + Activer une sonnerie personnalisée + + + + Connectivity + Connectivité + + + + STUN Address + + + + + Use STUN + Utiliser STUN + + + + Use UPnP + + + + + Use TURN + Utiliser le TURN + + + + TURN Password + + + + + TURN Username + + + + + TURN Address + + + + + Media + Média + + + + Enable Video + Activer la vidéo + + + + Video Codecs + Codecs Vidéo + + + + Audio Codecs + Codecs Audio + + + + Audio Files (*.wav *.ogg *.opus *.mp3 *aiff *wma) + + + + + Add a custom ringtone + Ajouter une sonnerie personnalisée + + + + AdvancedSettingsWidget + + + Form + Formulaire + + + + Call Settings + Paramètres d'appel + + + + Allow Calls From Untrusted Peers + Autoriser les appels d'une source inconnue + + + + Auto Answer Calls + Réponse automatique aux appels + + + + Enable Custom Ringtone + Activer une sonnerie personnalisée + + + + Add a custom ringtone + Ajouter une sonnerie personnalisée + + + + Name Server + Nom du serveur + + + + Address + Adresse + + + + OpenDHT Configuration + Configuration de l'OpenDHT + + + + Enable Proxy + Activer le Proxy + + + + Bootstrap + Amorcer + + + + Security + Sécurité + + + + Private Key Password + Mot de passe de la clé privée + + + + User Certificate + certificat d'utilisateur + + + + Private Key + Clé privée + + + + CA Certificate + Certificat CA + + + + Connectivity + Connectivité + + + + Use STUN + Utiliser STUN + + + + STUN Address + + + + + Use UPnP + + + + + Use TURN + Utiliser le TURN + + + + TURN Password + + + + + TURN Username + + + + + TURN Address + + + + + Media + Média + + + + Enable Video + Activer la vidéo + + + + Audio Codecs + Codecs Audio + + + + Video Codecs + Codecs Vidéo + + + + Audio Files (*.wav *.ogg *.opus *.mp3 *aiff *wma) + + + + + AnimatedOverlay + + + Form + Formulaire + + + + BannedItemWidget + + + Form + Formulaire + + + + name + + + + + id + + + + + CallWidget + + + Show conversations + + + + + Conversations + Conversations + + + + Search contact text input + + + + + Jami is free software for universal communication which respects the freedoms and privacy of its users. + Jami est un logiciel libre de communication universel qui respecte la vie privée et l'intimité de ses utilisateurs. + + + + + This is your ID. +Copy and share it with your friends! + + + + + + Show ring ID QR code + + + + + Share ring ID button + Bouton partager l'identificateur Ring + + + + Double-click to copy + Double-cliquez pour copier + + + + Error while generating QR Code + Une erreur s'est produite lors de la génération du code QR + + + + + best name + + + + + best Id + + + + + Back to homepage button + + + + + Add to contacts + Ajouter aux contacts + + + + Show invites + Montrer les invitations + + + + Invites + Invitations + + + + + Find a new or existing contact + Trouver un nouveau contact ou un contact existant + + + + Wants to talk to you! + veut vous parler! + + + + Answer incoming call button + Répondre à l'appel entrant + + + + Ignore incoming call button + Ignorer l'appel entrant + + + + Answer + Répondre + + + + Ignore + Ignorer + + + + Cancel outgoing call + Annuler l'appel sortant + + + + Cancel + Annuler + + + + Start video call + Démarrer appel video + + + + Start audio call + Démarrer appel audio + + + + Clear conversation + Effacer la conversation + + + + Remove contact + Supprimer contact + + + + Block contact + Bloquer le contact + + + + Copy number + Copier le numéro + + + + Search your received invitations + Recherchez vos invitations reçues + + + + Contact me on Jami + Contactez-moi sur Jami + + + + My Id is : + Mon identifiant est : + + + + %1 + %1 is the contact username + %1 + + + + %1 + %1 is the contact unique identifier + %1 + + + + Call incoming from %1 + Appel entrant de %1 + + + + DeleteAccountDialog + + + Account deletion + Suppression de compte + + + + Do you really want to delete the following account? + + + + + If this account hasn't been exported, or added to another device, it will be irrevocably lost. + + + + + Permanently delete account + Supprimer définitivement le compte + + + + Delete + Supprimer + + + + Cancel account deletion + + + + + Cancel + Annuler + + + + DeviceItemWidget + + + Form + Formulaire + + + + Device Id + + + + + this device + cet appareil + + + + InviteButtonsWidget + + + Accept + Accepter + + + + Refuse + Refuser + + + + Block + Bloquer + + + + LinkDeviceDialog + + + Dialog + Dialogue + + + + Enter your account password + + + + + Password + Mot de passe + + + + Ok + Ok + + + + Cancel + Annuler + + + + Exporting account + + + + + Your PIN is + + + + + PIN + NIP + + + + This pin and the account password should be entered in your device within 10 minutes. + + + + + Close + Fermer + + + + Link Another Device + Connecter un autre appareil + + + + Incorrect password + Mot de passe incorrect + + + + Something went wrong. +Please try again later. + Une erreur s'est produite. +Veuillez réessayer plus tard. + + + + MainWindow + + + Settings + Réglages + + + + Exit + Quitter + + + + About + À propos + + + + Jami + Jami + + + + NameRegistrationDialog + + + Set Registered Name + + + + + Enter your account password + + + + + Password text input + Entrée du mot de passe + + + + Password text entry + + + + + Password + Mot de passe + + + + Register + Inscription + + + + Cancel + Annuler + + + + Registering Name + + + + + Something went wrong + Une erreur s'est produite + + + + Close + Fermer + + + + Incorrect password + Mot de passe incorrect + + + + Network error + Erreur de réseau + + + + NewWizardWidget + + + Form + Formulaire + + + + Welcome Label + + + + + Welcome to + + + + + Welcome Logo + + + + + Create Jami account button + + + + + Push button for Jami account creation start trigger + + + + + Create a Jami account + Créer un compte Jami + + + + Link device button + + + + + Push button for device linkage start trigger + + + + + Link this device to an account + Associer cet appareil à un compte + + + + Create Jami SIP account button + + + + + Push button for Jami SIP account creation start trigger + + + + + Create a SIP account + Créer un compte SIP + + + + Link this device to an existing account + Associer cet appareil avec un compte existant + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Ubuntu'; font-size:14px; color:#555555;">To link this device to another account, you first </span><span style=" font-family:'Ubuntu'; font-size:14px; font-weight:600; color:#555555;">need to obtain a PIN</span><span style=" font-family:'Ubuntu'; font-size:14px; color:#555555;"> code. To generate the PIN code:</span></p> +<ol style="margin-top: 0px; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; -qt-list-indent: 1;"><li style=" font-family:'Ubuntu'; font-size:14px; color:#555555;" style=" margin-top:12px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:14px;">Go to the </span><span style=" font-size:14px; font-weight:600;">Account management setting</span><span style=" font-size:14px;"> of a previous device</span></li> +<li style=" font-family:'Ubuntu'; font-size:14px; color:#555555;" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:14px;">Choose the </span><span style=" font-size:14px; font-weight:600;">Jami account</span><span style=" font-size:14px;"> you want to use</span></li> +<li style=" font-family:'Ubuntu'; font-size:14px; color:#555555;" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:14px;">Go to the </span><span style=" font-size:14px; font-weight:600;">Devices</span><span style=" font-size:14px;"> tab</span></li> +<li style=" font-family:'Ubuntu'; font-size:14px; color:#555555;" style=" margin-top:0px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:14px;">Select </span><span style=" font-size:14px; font-weight:600;">Add a device</span></li></ol> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Ubuntu'; font-size:14px; color:#555555;">You will get the necessary PIN to complete this form. The PIN is only valid for </span><span style=" font-family:'Ubuntu'; font-size:14px; font-weight:600; color:#555555;">10 minutes</span><span style=" font-family:'Ubuntu'; font-size:10px; color:#555555;">.</span></p></body></html> + + + + + Enter your pin: + Entrer votre NIP : + + + + Or import a file: + Ou importer une archive de compte Ring : + + + + Link from exported account archive file + + + + + + + (None) + (aucun) + + + + Password: + Mot de passe: + + + + + Profile + Profil + + + + + Profile name + + + + + Account + Compte + + + + Register your username. +This will reserve the username so that only you can use it. +Your friends will be able to call you with your usename +instead of using your ID. + + + + + Public username checkbox + + + + + Checkbox selecting if the user wants a public username + + + + + Register public username + Enregistrer un nom d'utilisateur public + + + + Public username edit + Modification du nom d'utilisateur public + + + + Choose your username + Choisissez votre nom d'utilisateur + + + + Password text input + Entrée du mot de passe + + + + Password text entry + + + + + + Password + Mot de passe + + + + + Password confirmation text input + Mot de confirmation de saisie de texte + + + + Confirm password + Confirmer le mot de passe + + + + SIP Account + Compte SIP + + + + SIP Server edit + + + + + Server + + + + + SIP proxy input + + + + + SIP proxy text entry + + + + + Proxy + Proxy + + + + SIP username input + Entrée du username SIP + + + + SIP Password text entry + + + + + Username + Nom d'utilisateur + + + + + SIP Password text input + + + + + Generating your Jami account… + + + + + Previous page button + Bouton page précédente + + + + push button to access previous page of wizard + + + + + Previous + Précédent + + + + Cancel account create/link + + + + + push button to cancel account creation or linking + + + + + Back + Précédent + + + + Next page Button + Bouton page suivante + + + + Push button to access next page of wizard + Appuyer sur le bouton pour accéder à la prochaine page de l'assistant + + + + Next + Suivant + + + + Open File + Ouvrir un fichier + + + + Jami archive files (*.gz); All files (*) + + + + + Your account needs to be migrated. Enter your password. + + + + + Migrating your Jami account... + + + + + Importing account archive... + + + + + Generating your Jami account... + + + + + Generating your SIP account... + + + + + Error creating account + + + + + PasswordDialog + + + Change Account Password + + + + + Enter Current Password + + + + + Enter New Password + Entrer un nouveau mot de passe + + + + Confirm New Password + Confirmer votre mot de passe + + + + Confirm + + + + + Cancel + Annuler + + + + Current Password Incorrect + + + + + PhotoBoothDialog + + + Photobooth + + + + + PhotoboothWidget + + + Form + Formulaire + + + + Photobooth display + + + + + Choose File + Choisir le fichier + + + + Image Files (*.jpg *.jpeg *.png) + + + + + PrivateBridging + + + Choose File + Choisir le fichier + + + + Files (*) + Fichiers (*) + + + + QObject + + + No default mail client found + Aucun client de courriel par défaut n'a été trouvé + + + + + Edit Device Name + + + + + Unlink Device From Account + + + + + Save new device name + + + + + Add as contact + + + + + RingButton + + + Select folder + + + + + SettingsWidget + + + Form + Formulaire + + + + Settings + Réglages + + + + Account + Compte + + + + + General + Général + + + + + Audio / Video + + + + + System + Système + + + + Enable desktop notifications + + + + + Keep minimized on close + + + + + Download folder + + + + + Save in + + + + + Always Recording + + + + + Updates + + + + + Check for updates automatically every + + + + + Interval between update checks in days selector + + + + + days + + + + + Check for updates now button + + + + + Check for updates now + Vérifier les mises à nouveaux maintenant + + + + Password + Mot de passe + + + + + Enable + Activé + + + + toggle enable notifications + + + + + Toggle keep minimized on close + + + + + Call Recordings + + + + + Toggle automatic updates + + + + + Jami Account + + + + + + Profile + Profil + + + + + Identity + Identité + + + + Id + + + + + Registered name + Nom enregistré + + + + Type here to register a username + + + + + Register + Inscription + + + + Change Password + + + + + Export Account + Sauvegarder Compte + + + + + Delete Account + + + + + Linked Devices + + + + + Link Another Device + Connecter un autre appareil + + + + Banned Contacts + Contacts bloqués + + + + Format + + + + + Video device framerate selector + + + + + Preview unavailable + + + + + + Advanced Account Settings + + + + + SIP Account + Compte SIP + + + + Username + Nom d'utilisateur + + + + Hostname + Nom de domaine + + + + Proxy + Proxy + + + + Audio + Audio + + + + Microphone + + + + + Audio input device selector + + + + + Output Device + Périphérique de sortie + + + + Choose the output device + + + + + Video + Vidéo + + + + Device + Appareil + + + + Video device selector + + + + + A registered name should not have any spaces and must be at least three letters long + + + + + This name is already taken + + + + + + Enter an alias + + + + + Register this name + + + + + Remove Device + + + + + Enter this account's password to confirm the removal of this device + + + + + Are you sure you wish to remove this device? + + + + + Export Account Here + + + + + Select A Folder For Your Downloads + + + + + Select A Folder For Your Recordings + + + + + VideoOverlay + + + Call on Hold + Appel en attente + + + + Hold / Unhold + Mettre en attente / Reprendre l'appel + + + + Chat + Clavardage + + + + Mute Mic + Couper le microphone + + + + Record call + + + + + Name label + Nom de l'étiquette + + + + Time elapsed + + + + + 00:00 + 00:00 + + + + Hangup + Raccrocher + + + + Mute Video + Couper le son de la vidéo + + + + VideoView + + + Share entire screen + Partager la totalité de l'écran + + + + Share screen area + Partager une partie de l'écran + + + + Share file + Partager le fichier + + + \ No newline at end of file diff --git a/translations/ring_client_windows_fr_CH.ts b/translations/ring_client_windows_fr_CH.ts new file mode 100644 index 00000000..b556cef8 --- /dev/null +++ b/translations/ring_client_windows_fr_CH.ts @@ -0,0 +1,1589 @@ + + + AboutDialog + + + + About + + + + + about button + + + + + credits button + + + + + Credits + + + + + Free as in Freedom + + + + + The Microsoft Windows client for Jami. +Jami is a secured and distributed communication software. + + + + + version + + + + + Created by: + + + + + Artwork by: + + + + + Based on the SFLPhone project + + + + + AccountItemDelegate + + + Add Account + + + + + AdvancedSIPSettingsWidget + + + Form + + + + + Call Settings + + + + + Auto Answer Calls + + + + + Enable Custom Ringtone + + + + + Connectivity + Connectivité + + + + STUN Address + + + + + Use STUN + Utiliser STUN + + + + Use UPnP + + + + + Use TURN + Utiliser le TURN + + + + TURN Password + + + + + TURN Username + + + + + TURN Address + + + + + Media + + + + + Enable Video + + + + + Video Codecs + + + + + Audio Codecs + + + + + Audio Files (*.wav *.ogg *.opus *.mp3 *aiff *wma) + + + + + Add a custom ringtone + + + + + AdvancedSettingsWidget + + + Form + + + + + Call Settings + + + + + Allow Calls From Untrusted Peers + + + + + Auto Answer Calls + + + + + Enable Custom Ringtone + + + + + Add a custom ringtone + + + + + Name Server + + + + + Address + Adresse + + + + OpenDHT Configuration + + + + + Enable Proxy + + + + + Bootstrap + Amorcer + + + + Security + Sécurité + + + + Private Key Password + + + + + User Certificate + + + + + Private Key + + + + + CA Certificate + + + + + Connectivity + Connectivité + + + + Use STUN + Utiliser STUN + + + + STUN Address + + + + + Use UPnP + + + + + Use TURN + Utiliser le TURN + + + + TURN Password + + + + + TURN Username + + + + + TURN Address + + + + + Media + + + + + Enable Video + + + + + Audio Codecs + + + + + Video Codecs + + + + + Audio Files (*.wav *.ogg *.opus *.mp3 *aiff *wma) + + + + + AnimatedOverlay + + + Form + + + + + BannedItemWidget + + + Form + + + + + name + + + + + id + + + + + CallWidget + + + Show conversations + + + + + Conversations + Conversations + + + + Search contact text input + + + + + Jami is free software for universal communication which respects the freedoms and privacy of its users. + Jami est un logiciel libre de communication universel qui respecte la vie privée et l'intimité de ses utilisateurs. + + + + + This is your ID. +Copy and share it with your friends! + + + + + + Show ring ID QR code + + + + + Share ring ID button + + + + + Double-click to copy + + + + + Error while generating QR Code + + + + + + best name + + + + + best Id + + + + + Back to homepage button + + + + + Add to contacts + Ajouter aux contacts + + + + Show invites + + + + + Invites + + + + + + Find a new or existing contact + + + + + Wants to talk to you! + + + + + Answer incoming call button + + + + + Ignore incoming call button + + + + + Answer + + + + + Ignore + + + + + Cancel outgoing call + + + + + Cancel + Annuler + + + + Start video call + Démarrer appel video + + + + Start audio call + Démarrer appel audio + + + + Clear conversation + Effacer la conversation + + + + Remove contact + + + + + Block contact + Bloquer le contact + + + + Copy number + + + + + Search your received invitations + + + + + Contact me on Jami + + + + + My Id is : + + + + + %1 + %1 is the contact username + + + + + %1 + %1 is the contact unique identifier + + + + + Call incoming from %1 + + + + + DeleteAccountDialog + + + Account deletion + + + + + Do you really want to delete the following account? + + + + + If this account hasn't been exported, or added to another device, it will be irrevocably lost. + + + + + Permanently delete account + + + + + Delete + + + + + Cancel account deletion + + + + + Cancel + Annuler + + + + DeviceItemWidget + + + Form + + + + + Device Id + + + + + this device + + + + + InviteButtonsWidget + + + Accept + Accepter + + + + Refuse + Refuser + + + + Block + + + + + LinkDeviceDialog + + + Dialog + + + + + Enter your account password + + + + + Password + + + + + Ok + OK + + + + Cancel + Annuler + + + + Exporting account + + + + + Your PIN is + + + + + PIN + + + + + This pin and the account password should be entered in your device within 10 minutes. + + + + + Close + + + + + Link Another Device + + + + + Incorrect password + + + + + Something went wrong. +Please try again later. + + + + + MainWindow + + + Settings + + + + + Exit + + + + + About + + + + + Jami + Jami + + + + NameRegistrationDialog + + + Set Registered Name + + + + + Enter your account password + + + + + Password text input + + + + + Password text entry + + + + + Password + + + + + Register + Enregistrer + + + + Cancel + Annuler + + + + Registering Name + + + + + Something went wrong + + + + + Close + + + + + Incorrect password + + + + + Network error + + + + + NewWizardWidget + + + Form + + + + + Welcome Label + + + + + Welcome to + + + + + Welcome Logo + + + + + Create Jami account button + + + + + Push button for Jami account creation start trigger + + + + + Create a Jami account + Créer un compte Jami + + + + Link device button + + + + + Push button for device linkage start trigger + + + + + Link this device to an account + Lier cet appareil à un compte + + + + Create Jami SIP account button + + + + + Push button for Jami SIP account creation start trigger + + + + + Create a SIP account + + + + + Link this device to an existing account + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Ubuntu'; font-size:14px; color:#555555;">To link this device to another account, you first </span><span style=" font-family:'Ubuntu'; font-size:14px; font-weight:600; color:#555555;">need to obtain a PIN</span><span style=" font-family:'Ubuntu'; font-size:14px; color:#555555;"> code. To generate the PIN code:</span></p> +<ol style="margin-top: 0px; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; -qt-list-indent: 1;"><li style=" font-family:'Ubuntu'; font-size:14px; color:#555555;" style=" margin-top:12px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:14px;">Go to the </span><span style=" font-size:14px; font-weight:600;">Account management setting</span><span style=" font-size:14px;"> of a previous device</span></li> +<li style=" font-family:'Ubuntu'; font-size:14px; color:#555555;" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:14px;">Choose the </span><span style=" font-size:14px; font-weight:600;">Jami account</span><span style=" font-size:14px;"> you want to use</span></li> +<li style=" font-family:'Ubuntu'; font-size:14px; color:#555555;" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:14px;">Go to the </span><span style=" font-size:14px; font-weight:600;">Devices</span><span style=" font-size:14px;"> tab</span></li> +<li style=" font-family:'Ubuntu'; font-size:14px; color:#555555;" style=" margin-top:0px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:14px;">Select </span><span style=" font-size:14px; font-weight:600;">Add a device</span></li></ol> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Ubuntu'; font-size:14px; color:#555555;">You will get the necessary PIN to complete this form. The PIN is only valid for </span><span style=" font-family:'Ubuntu'; font-size:14px; font-weight:600; color:#555555;">10 minutes</span><span style=" font-family:'Ubuntu'; font-size:10px; color:#555555;">.</span></p></body></html> + + + + + Enter your pin: + + + + + Or import a file: + + + + + Link from exported account archive file + + + + + + + (None) + + + + + Password: + Mot de passe : + + + + + Profile + Profil + + + + + Profile name + + + + + Account + Compte + + + + Register your username. +This will reserve the username so that only you can use it. +Your friends will be able to call you with your usename +instead of using your ID. + + + + + Public username checkbox + + + + + Checkbox selecting if the user wants a public username + + + + + Register public username + Enregistrer un nom d'utilisateur public + + + + Public username edit + + + + + Choose your username + + + + + Password text input + + + + + Password text entry + + + + + + Password + + + + + + Password confirmation text input + + + + + Confirm password + + + + + SIP Account + + + + + SIP Server edit + + + + + Server + + + + + SIP proxy input + + + + + SIP proxy text entry + + + + + Proxy + + + + + SIP username input + + + + + SIP Password text entry + + + + + Username + + + + + + SIP Password text input + + + + + Generating your Jami account… + + + + + Previous page button + + + + + push button to access previous page of wizard + + + + + Previous + + + + + Cancel account create/link + + + + + push button to cancel account creation or linking + + + + + Back + + + + + Next page Button + + + + + Push button to access next page of wizard + + + + + Next + Suivant + + + + Open File + + + + + Jami archive files (*.gz); All files (*) + + + + + Your account needs to be migrated. Enter your password. + + + + + Migrating your Jami account... + + + + + Importing account archive... + + + + + Generating your Jami account... + + + + + Generating your SIP account... + + + + + Error creating account + + + + + PasswordDialog + + + Change Account Password + + + + + Enter Current Password + + + + + Enter New Password + + + + + Confirm New Password + + + + + Confirm + + + + + Cancel + Annuler + + + + Current Password Incorrect + + + + + PhotoBoothDialog + + + Photobooth + + + + + PhotoboothWidget + + + Form + + + + + Photobooth display + + + + + Choose File + + + + + Image Files (*.jpg *.jpeg *.png) + + + + + PrivateBridging + + + Choose File + + + + + Files (*) + + + + + QObject + + + No default mail client found + + + + + + Edit Device Name + + + + + Unlink Device From Account + + + + + Save new device name + + + + + Add as contact + + + + + RingButton + + + Select folder + + + + + SettingsWidget + + + Form + + + + + Settings + + + + + Account + Compte + + + + + General + Général + + + + + Audio / Video + + + + + System + + + + + Enable desktop notifications + + + + + Keep minimized on close + + + + + Download folder + + + + + Save in + + + + + Always Recording + + + + + Updates + + + + + Check for updates automatically every + + + + + Interval between update checks in days selector + + + + + days + + + + + Check for updates now button + + + + + Check for updates now + + + + + Password + + + + + + Enable + Activé + + + + toggle enable notifications + + + + + Toggle keep minimized on close + + + + + Call Recordings + + + + + Toggle automatic updates + + + + + Jami Account + + + + + + Profile + Profil + + + + + Identity + + + + + Id + + + + + Registered name + + + + + Type here to register a username + + + + + Register + Enregistrer + + + + Change Password + + + + + Export Account + Sauvegarder Compte + + + + + Delete Account + + + + + Linked Devices + + + + + Link Another Device + + + + + Banned Contacts + Contacts bloqués + + + + Format + + + + + Video device framerate selector + + + + + Preview unavailable + + + + + + Advanced Account Settings + + + + + SIP Account + + + + + Username + + + + + Hostname + + + + + Proxy + + + + + Audio + Audio + + + + Microphone + + + + + Audio input device selector + + + + + Output Device + + + + + Choose the output device + + + + + Video + Vidéo + + + + Device + + + + + Video device selector + + + + + A registered name should not have any spaces and must be at least three letters long + + + + + This name is already taken + + + + + + Enter an alias + + + + + Register this name + + + + + Remove Device + + + + + Enter this account's password to confirm the removal of this device + + + + + Are you sure you wish to remove this device? + + + + + Export Account Here + + + + + Select A Folder For Your Downloads + + + + + Select A Folder For Your Recordings + + + + + VideoOverlay + + + Call on Hold + + + + + Hold / Unhold + + + + + Chat + + + + + Mute Mic + + + + + Record call + + + + + Name label + + + + + Time elapsed + + + + + 00:00 + + + + + Hangup + + + + + Mute Video + + + + + VideoView + + + Share entire screen + + + + + Share screen area + + + + + Share file + + + + \ No newline at end of file diff --git a/translations/ring_client_windows_fr_FR.ts b/translations/ring_client_windows_fr_FR.ts new file mode 100644 index 00000000..c8aa9539 --- /dev/null +++ b/translations/ring_client_windows_fr_FR.ts @@ -0,0 +1,1589 @@ + + + AboutDialog + + + + About + A propos + + + + about button + à propos du bouton + + + + credits button + + + + + Credits + Crédits + + + + Free as in Freedom + + + + + The Microsoft Windows client for Jami. +Jami is a secured and distributed communication software. + + + + + version + version + + + + Created by: + créer par + + + + Artwork by: + + + + + Based on the SFLPhone project + + + + + AccountItemDelegate + + + Add Account + + + + + AdvancedSIPSettingsWidget + + + Form + + + + + Call Settings + + + + + Auto Answer Calls + + + + + Enable Custom Ringtone + + + + + Connectivity + Connectivité + + + + STUN Address + + + + + Use STUN + Utiliser STUN + + + + Use UPnP + + + + + Use TURN + Utiliser le TURN + + + + TURN Password + + + + + TURN Username + + + + + TURN Address + + + + + Media + + + + + Enable Video + + + + + Video Codecs + + + + + Audio Codecs + + + + + Audio Files (*.wav *.ogg *.opus *.mp3 *aiff *wma) + + + + + Add a custom ringtone + + + + + AdvancedSettingsWidget + + + Form + + + + + Call Settings + + + + + Allow Calls From Untrusted Peers + + + + + Auto Answer Calls + + + + + Enable Custom Ringtone + + + + + Add a custom ringtone + + + + + Name Server + + + + + Address + Adresse + + + + OpenDHT Configuration + + + + + Enable Proxy + + + + + Bootstrap + Amorcer + + + + Security + securité + + + + Private Key Password + + + + + User Certificate + + + + + Private Key + + + + + CA Certificate + + + + + Connectivity + Connectivité + + + + Use STUN + Utiliser STUN + + + + STUN Address + + + + + Use UPnP + + + + + Use TURN + Utiliser le TURN + + + + TURN Password + + + + + TURN Username + + + + + TURN Address + + + + + Media + + + + + Enable Video + + + + + Audio Codecs + + + + + Video Codecs + + + + + Audio Files (*.wav *.ogg *.opus *.mp3 *aiff *wma) + + + + + AnimatedOverlay + + + Form + + + + + BannedItemWidget + + + Form + + + + + name + + + + + id + + + + + CallWidget + + + Show conversations + + + + + Conversations + Conversation + + + + Search contact text input + + + + + Jami is free software for universal communication which respects the freedoms and privacy of its users. + Jami est un logiciel libre de communication universel qui respecte la vie privée et l'intimité de ses utilisateurs. + + + + + This is your ID. +Copy and share it with your friends! + + + + + + Show ring ID QR code + + + + + Share ring ID button + + + + + Double-click to copy + + + + + Error while generating QR Code + + + + + + best name + + + + + best Id + + + + + Back to homepage button + + + + + Add to contacts + Ajouter dans les contacts + + + + Show invites + + + + + Invites + + + + + + Find a new or existing contact + + + + + Wants to talk to you! + + + + + Answer incoming call button + + + + + Ignore incoming call button + + + + + Answer + Répondre + + + + Ignore + Ignorer + + + + Cancel outgoing call + + + + + Cancel + Annuler + + + + Start video call + Démarrer appel video + + + + Start audio call + Démarrer appel audio + + + + Clear conversation + Effacer la conversation + + + + Remove contact + + + + + Block contact + Bloquer le contact + + + + Copy number + Copier le numéro de téléphone + + + + Search your received invitations + + + + + Contact me on Jami + + + + + My Id is : + + + + + %1 + %1 is the contact username + + + + + %1 + %1 is the contact unique identifier + + + + + Call incoming from %1 + + + + + DeleteAccountDialog + + + Account deletion + + + + + Do you really want to delete the following account? + + + + + If this account hasn't been exported, or added to another device, it will be irrevocably lost. + + + + + Permanently delete account + + + + + Delete + Supprimer + + + + Cancel account deletion + + + + + Cancel + Annuler + + + + DeviceItemWidget + + + Form + + + + + Device Id + + + + + this device + + + + + InviteButtonsWidget + + + Accept + Accepter + + + + Refuse + Refuser + + + + Block + Bloquer + + + + LinkDeviceDialog + + + Dialog + + + + + Enter your account password + + + + + Password + mot de passe + + + + Ok + d'accord + + + + Cancel + Annuler + + + + Exporting account + + + + + Your PIN is + + + + + PIN + PIN + + + + This pin and the account password should be entered in your device within 10 minutes. + + + + + Close + + + + + Link Another Device + + + + + Incorrect password + + + + + Something went wrong. +Please try again later. + + + + + MainWindow + + + Settings + Réglages + + + + Exit + + + + + About + A propos + + + + Jami + Jami + + + + NameRegistrationDialog + + + Set Registered Name + + + + + Enter your account password + + + + + Password text input + + + + + Password text entry + + + + + Password + mot de passe + + + + Register + Enregistrer + + + + Cancel + Annuler + + + + Registering Name + + + + + Something went wrong + + + + + Close + + + + + Incorrect password + + + + + Network error + + + + + NewWizardWidget + + + Form + + + + + Welcome Label + + + + + Welcome to + + + + + Welcome Logo + + + + + Create Jami account button + + + + + Push button for Jami account creation start trigger + + + + + Create a Jami account + Créer un compte Jami + + + + Link device button + + + + + Push button for device linkage start trigger + + + + + Link this device to an account + Lier cet appareil à un compte + + + + Create Jami SIP account button + + + + + Push button for Jami SIP account creation start trigger + + + + + Create a SIP account + + + + + Link this device to an existing account + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Ubuntu'; font-size:14px; color:#555555;">To link this device to another account, you first </span><span style=" font-family:'Ubuntu'; font-size:14px; font-weight:600; color:#555555;">need to obtain a PIN</span><span style=" font-family:'Ubuntu'; font-size:14px; color:#555555;"> code. To generate the PIN code:</span></p> +<ol style="margin-top: 0px; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; -qt-list-indent: 1;"><li style=" font-family:'Ubuntu'; font-size:14px; color:#555555;" style=" margin-top:12px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:14px;">Go to the </span><span style=" font-size:14px; font-weight:600;">Account management setting</span><span style=" font-size:14px;"> of a previous device</span></li> +<li style=" font-family:'Ubuntu'; font-size:14px; color:#555555;" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:14px;">Choose the </span><span style=" font-size:14px; font-weight:600;">Jami account</span><span style=" font-size:14px;"> you want to use</span></li> +<li style=" font-family:'Ubuntu'; font-size:14px; color:#555555;" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:14px;">Go to the </span><span style=" font-size:14px; font-weight:600;">Devices</span><span style=" font-size:14px;"> tab</span></li> +<li style=" font-family:'Ubuntu'; font-size:14px; color:#555555;" style=" margin-top:0px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:14px;">Select </span><span style=" font-size:14px; font-weight:600;">Add a device</span></li></ol> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Ubuntu'; font-size:14px; color:#555555;">You will get the necessary PIN to complete this form. The PIN is only valid for </span><span style=" font-family:'Ubuntu'; font-size:14px; font-weight:600; color:#555555;">10 minutes</span><span style=" font-family:'Ubuntu'; font-size:10px; color:#555555;">.</span></p></body></html> + + + + + Enter your pin: + + + + + Or import a file: + + + + + Link from exported account archive file + + + + + + + (None) + + + + + Password: + Mot de passe : + + + + + Profile + Profil + + + + + Profile name + + + + + Account + compte + + + + Register your username. +This will reserve the username so that only you can use it. +Your friends will be able to call you with your usename +instead of using your ID. + + + + + Public username checkbox + + + + + Checkbox selecting if the user wants a public username + + + + + Register public username + Enregistrer un nom d'utilisateur public + + + + Public username edit + + + + + Choose your username + + + + + Password text input + + + + + Password text entry + + + + + + Password + mot de passe + + + + + Password confirmation text input + + + + + Confirm password + + + + + SIP Account + Compte SIP + + + + SIP Server edit + + + + + Server + + + + + SIP proxy input + + + + + SIP proxy text entry + + + + + Proxy + + + + + SIP username input + + + + + SIP Password text entry + + + + + Username + nom d'utilisateur + + + + + SIP Password text input + + + + + Generating your Jami account… + + + + + Previous page button + + + + + push button to access previous page of wizard + + + + + Previous + + + + + Cancel account create/link + + + + + push button to cancel account creation or linking + + + + + Back + Retour + + + + Next page Button + + + + + Push button to access next page of wizard + + + + + Next + Suivant + + + + Open File + + + + + Jami archive files (*.gz); All files (*) + + + + + Your account needs to be migrated. Enter your password. + + + + + Migrating your Jami account... + + + + + Importing account archive... + + + + + Generating your Jami account... + + + + + Generating your SIP account... + + + + + Error creating account + + + + + PasswordDialog + + + Change Account Password + + + + + Enter Current Password + + + + + Enter New Password + + + + + Confirm New Password + + + + + Confirm + + + + + Cancel + Annuler + + + + Current Password Incorrect + + + + + PhotoBoothDialog + + + Photobooth + + + + + PhotoboothWidget + + + Form + + + + + Photobooth display + + + + + Choose File + choisir un fichier + + + + Image Files (*.jpg *.jpeg *.png) + + + + + PrivateBridging + + + Choose File + choisir un fichier + + + + Files (*) + + + + + QObject + + + No default mail client found + + + + + + Edit Device Name + + + + + Unlink Device From Account + + + + + Save new device name + + + + + Add as contact + + + + + RingButton + + + Select folder + + + + + SettingsWidget + + + Form + + + + + Settings + Réglages + + + + Account + compte + + + + + General + Général + + + + + Audio / Video + + + + + System + Système + + + + Enable desktop notifications + + + + + Keep minimized on close + + + + + Download folder + + + + + Save in + + + + + Always Recording + + + + + Updates + + + + + Check for updates automatically every + + + + + Interval between update checks in days selector + + + + + days + + + + + Check for updates now button + + + + + Check for updates now + + + + + Password + mot de passe + + + + + Enable + Activé + + + + toggle enable notifications + + + + + Toggle keep minimized on close + + + + + Call Recordings + + + + + Toggle automatic updates + + + + + Jami Account + + + + + + Profile + Profil + + + + + Identity + + + + + Id + + + + + Registered name + + + + + Type here to register a username + + + + + Register + Enregistrer + + + + Change Password + + + + + Export Account + Sauvegarder Compte + + + + + Delete Account + + + + + Linked Devices + + + + + Link Another Device + + + + + Banned Contacts + Contacts bloqués + + + + Format + + + + + Video device framerate selector + + + + + Preview unavailable + + + + + + Advanced Account Settings + + + + + SIP Account + Compte SIP + + + + Username + nom d'utilisateur + + + + Hostname + nom d'hôte + + + + Proxy + + + + + Audio + Audio + + + + Microphone + + + + + Audio input device selector + + + + + Output Device + + + + + Choose the output device + + + + + Video + Vidéo + + + + Device + + + + + Video device selector + + + + + A registered name should not have any spaces and must be at least three letters long + + + + + This name is already taken + + + + + + Enter an alias + + + + + Register this name + + + + + Remove Device + + + + + Enter this account's password to confirm the removal of this device + + + + + Are you sure you wish to remove this device? + + + + + Export Account Here + + + + + Select A Folder For Your Downloads + + + + + Select A Folder For Your Recordings + + + + + VideoOverlay + + + Call on Hold + + + + + Hold / Unhold + + + + + Chat + + + + + Mute Mic + + + + + Record call + + + + + Name label + + + + + Time elapsed + + + + + 00:00 + + + + + Hangup + + + + + Mute Video + Vidéo muette + + + + VideoView + + + Share entire screen + + + + + Share screen area + + + + + Share file + Partager le fichier + + + \ No newline at end of file diff --git a/translations/ring_client_windows_gl.ts b/translations/ring_client_windows_gl.ts new file mode 100644 index 00000000..12a7bf8f --- /dev/null +++ b/translations/ring_client_windows_gl.ts @@ -0,0 +1,1589 @@ + + + AboutDialog + + + + About + + + + + about button + + + + + credits button + + + + + Credits + Cŕedito + + + + Free as in Freedom + Libre como en liberdade + + + + The Microsoft Windows client for Jami. +Jami is a secured and distributed communication software. + + + + + version + + + + + Created by: + + + + + Artwork by: + + + + + Based on the SFLPhone project + + + + + AccountItemDelegate + + + Add Account + + + + + AdvancedSIPSettingsWidget + + + Form + + + + + Call Settings + + + + + Auto Answer Calls + + + + + Enable Custom Ringtone + + + + + Connectivity + Conectividade + + + + STUN Address + + + + + Use STUN + Usar STUN + + + + Use UPnP + + + + + Use TURN + Usar TURN + + + + TURN Password + + + + + TURN Username + + + + + TURN Address + + + + + Media + Multimedia + + + + Enable Video + Activar vídeo + + + + Video Codecs + + + + + Audio Codecs + + + + + Audio Files (*.wav *.ogg *.opus *.mp3 *aiff *wma) + + + + + Add a custom ringtone + + + + + AdvancedSettingsWidget + + + Form + + + + + Call Settings + + + + + Allow Calls From Untrusted Peers + + + + + Auto Answer Calls + + + + + Enable Custom Ringtone + + + + + Add a custom ringtone + + + + + Name Server + + + + + Address + Enderezo + + + + OpenDHT Configuration + + + + + Enable Proxy + + + + + Bootstrap + Bootstrap + + + + Security + Seguridade + + + + Private Key Password + Contrasinal da chave privada + + + + User Certificate + Certificado de usuaria + + + + Private Key + + + + + CA Certificate + + + + + Connectivity + Conectividade + + + + Use STUN + Usar STUN + + + + STUN Address + + + + + Use UPnP + + + + + Use TURN + Usar TURN + + + + TURN Password + + + + + TURN Username + + + + + TURN Address + + + + + Media + Multimedia + + + + Enable Video + Activar vídeo + + + + Audio Codecs + + + + + Video Codecs + + + + + Audio Files (*.wav *.ogg *.opus *.mp3 *aiff *wma) + + + + + AnimatedOverlay + + + Form + + + + + BannedItemWidget + + + Form + + + + + name + + + + + id + + + + + CallWidget + + + Show conversations + Mostrar conversas + + + + Conversations + Conversas + + + + Search contact text input + + + + + Jami is free software for universal communication which respects the freedoms and privacy of its users. + Jami é software libre para comunicacións universais e que respecta as liberdades e privacidade das súas usuarias. + + + + + This is your ID. +Copy and share it with your friends! + + + + + + Show ring ID QR code + + + + + Share ring ID button + + + + + Double-click to copy + + + + + Error while generating QR Code + + + + + + best name + + + + + best Id + + + + + Back to homepage button + + + + + Add to contacts + Engadir a contactos + + + + Show invites + Mostrar convites + + + + Invites + + + + + + Find a new or existing contact + + + + + Wants to talk to you! + + + + + Answer incoming call button + + + + + Ignore incoming call button + + + + + Answer + + + + + Ignore + + + + + Cancel outgoing call + + + + + Cancel + Cancelar + + + + Start video call + Iniciar chamada de vídeo + + + + Start audio call + Iniciar chamada de audio + + + + Clear conversation + Limpar conversa + + + + Remove contact + + + + + Block contact + Bloquear contacto + + + + Copy number + Copiar número + + + + Search your received invitations + + + + + Contact me on Jami + + + + + My Id is : + + + + + %1 + %1 is the contact username + + + + + %1 + %1 is the contact unique identifier + + + + + Call incoming from %1 + + + + + DeleteAccountDialog + + + Account deletion + + + + + Do you really want to delete the following account? + + + + + If this account hasn't been exported, or added to another device, it will be irrevocably lost. + + + + + Permanently delete account + + + + + Delete + Eliminar + + + + Cancel account deletion + + + + + Cancel + Cancelar + + + + DeviceItemWidget + + + Form + + + + + Device Id + + + + + this device + este dispositivo + + + + InviteButtonsWidget + + + Accept + Aceptar + + + + Refuse + Rexeitar + + + + Block + Bloquar + + + + LinkDeviceDialog + + + Dialog + + + + + Enter your account password + + + + + Password + Contrasinal + + + + Ok + Ok + + + + Cancel + Cancelar + + + + Exporting account + + + + + Your PIN is + + + + + PIN + PIN + + + + This pin and the account password should be entered in your device within 10 minutes. + + + + + Close + + + + + Link Another Device + + + + + Incorrect password + + + + + Something went wrong. +Please try again later. + + + + + MainWindow + + + Settings + Axuste + + + + Exit + + + + + About + + + + + Jami + + + + + NameRegistrationDialog + + + Set Registered Name + + + + + Enter your account password + + + + + Password text input + + + + + Password text entry + + + + + Password + Contrasinal + + + + Register + Rexistro + + + + Cancel + Cancelar + + + + Registering Name + + + + + Something went wrong + + + + + Close + + + + + Incorrect password + + + + + Network error + Fallo na rede + + + + NewWizardWidget + + + Form + + + + + Welcome Label + + + + + Welcome to + + + + + Welcome Logo + + + + + Create Jami account button + + + + + Push button for Jami account creation start trigger + + + + + Create a Jami account + Crear conta Jami + + + + Link device button + + + + + Push button for device linkage start trigger + + + + + Link this device to an account + Ligar este dispositivo a unha conta + + + + Create Jami SIP account button + + + + + Push button for Jami SIP account creation start trigger + + + + + Create a SIP account + + + + + Link this device to an existing account + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Ubuntu'; font-size:14px; color:#555555;">To link this device to another account, you first </span><span style=" font-family:'Ubuntu'; font-size:14px; font-weight:600; color:#555555;">need to obtain a PIN</span><span style=" font-family:'Ubuntu'; font-size:14px; color:#555555;"> code. To generate the PIN code:</span></p> +<ol style="margin-top: 0px; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; -qt-list-indent: 1;"><li style=" font-family:'Ubuntu'; font-size:14px; color:#555555;" style=" margin-top:12px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:14px;">Go to the </span><span style=" font-size:14px; font-weight:600;">Account management setting</span><span style=" font-size:14px;"> of a previous device</span></li> +<li style=" font-family:'Ubuntu'; font-size:14px; color:#555555;" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:14px;">Choose the </span><span style=" font-size:14px; font-weight:600;">Jami account</span><span style=" font-size:14px;"> you want to use</span></li> +<li style=" font-family:'Ubuntu'; font-size:14px; color:#555555;" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:14px;">Go to the </span><span style=" font-size:14px; font-weight:600;">Devices</span><span style=" font-size:14px;"> tab</span></li> +<li style=" font-family:'Ubuntu'; font-size:14px; color:#555555;" style=" margin-top:0px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:14px;">Select </span><span style=" font-size:14px; font-weight:600;">Add a device</span></li></ol> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Ubuntu'; font-size:14px; color:#555555;">You will get the necessary PIN to complete this form. The PIN is only valid for </span><span style=" font-family:'Ubuntu'; font-size:14px; font-weight:600; color:#555555;">10 minutes</span><span style=" font-family:'Ubuntu'; font-size:10px; color:#555555;">.</span></p></body></html> + + + + + Enter your pin: + + + + + Or import a file: + + + + + Link from exported account archive file + + + + + + + (None) + + + + + Password: + Contrasinal: + + + + + Profile + Perfil + + + + + Profile name + + + + + Account + Conta + + + + Register your username. +This will reserve the username so that only you can use it. +Your friends will be able to call you with your usename +instead of using your ID. + + + + + Public username checkbox + + + + + Checkbox selecting if the user wants a public username + + + + + Register public username + Rexistrar o nome público de usuaria + + + + Public username edit + + + + + Choose your username + + + + + Password text input + + + + + Password text entry + + + + + + Password + Contrasinal + + + + + Password confirmation text input + + + + + Confirm password + Confirmar contrasinal + + + + SIP Account + + + + + SIP Server edit + + + + + Server + + + + + SIP proxy input + + + + + SIP proxy text entry + + + + + Proxy + Proxy + + + + SIP username input + + + + + SIP Password text entry + + + + + Username + Nome de usuaria + + + + + SIP Password text input + + + + + Generating your Jami account… + Estase a xerar a súa conta Jami... + + + + Previous page button + + + + + push button to access previous page of wizard + + + + + Previous + Anterior + + + + Cancel account create/link + + + + + push button to cancel account creation or linking + + + + + Back + Atrás + + + + Next page Button + + + + + Push button to access next page of wizard + + + + + Next + Seguinte + + + + Open File + + + + + Jami archive files (*.gz); All files (*) + + + + + Your account needs to be migrated. Enter your password. + + + + + Migrating your Jami account... + + + + + Importing account archive... + + + + + Generating your Jami account... + + + + + Generating your SIP account... + + + + + Error creating account + + + + + PasswordDialog + + + Change Account Password + + + + + Enter Current Password + + + + + Enter New Password + + + + + Confirm New Password + + + + + Confirm + + + + + Cancel + Cancelar + + + + Current Password Incorrect + + + + + PhotoBoothDialog + + + Photobooth + + + + + PhotoboothWidget + + + Form + + + + + Photobooth display + + + + + Choose File + + + + + Image Files (*.jpg *.jpeg *.png) + + + + + PrivateBridging + + + Choose File + + + + + Files (*) + + + + + QObject + + + No default mail client found + + + + + + Edit Device Name + + + + + Unlink Device From Account + + + + + Save new device name + + + + + Add as contact + + + + + RingButton + + + Select folder + + + + + SettingsWidget + + + Form + + + + + Settings + Axuste + + + + Account + Conta + + + + + General + Xeral + + + + + Audio / Video + + + + + System + Sistema + + + + Enable desktop notifications + + + + + Keep minimized on close + + + + + Download folder + Cartafol para descargas + + + + Save in + + + + + Always Recording + + + + + Updates + + + + + Check for updates automatically every + + + + + Interval between update checks in days selector + + + + + days + + + + + Check for updates now button + + + + + Check for updates now + + + + + Password + Contrasinal + + + + + Enable + Activar + + + + toggle enable notifications + + + + + Toggle keep minimized on close + + + + + Call Recordings + + + + + Toggle automatic updates + + + + + Jami Account + + + + + + Profile + Perfil + + + + + Identity + Identidade + + + + Id + + + + + Registered name + + + + + Type here to register a username + + + + + Register + Rexistro + + + + Change Password + Cambiar contrasinal + + + + Export Account + Exportar conta + + + + + Delete Account + + + + + Linked Devices + + + + + Link Another Device + + + + + Banned Contacts + Contactos excluídos + + + + Format + + + + + Video device framerate selector + + + + + Preview unavailable + + + + + + Advanced Account Settings + + + + + SIP Account + + + + + Username + Nome de usuaria + + + + Hostname + Servidor + + + + Proxy + Proxy + + + + Audio + Audio + + + + Microphone + + + + + Audio input device selector + + + + + Output Device + + + + + Choose the output device + + + + + Video + Vídeo + + + + Device + + + + + Video device selector + + + + + A registered name should not have any spaces and must be at least three letters long + + + + + This name is already taken + + + + + + Enter an alias + + + + + Register this name + + + + + Remove Device + + + + + Enter this account's password to confirm the removal of this device + + + + + Are you sure you wish to remove this device? + + + + + Export Account Here + + + + + Select A Folder For Your Downloads + + + + + Select A Folder For Your Recordings + + + + + VideoOverlay + + + Call on Hold + + + + + Hold / Unhold + + + + + Chat + Conversa + + + + Mute Mic + + + + + Record call + + + + + Name label + + + + + Time elapsed + + + + + 00:00 + 00:00 + + + + Hangup + + + + + Mute Video + Acalar vídeo + + + + VideoView + + + Share entire screen + + + + + Share screen area + + + + + Share file + Compartir ficheiro + + + \ No newline at end of file diff --git a/translations/ring_client_windows_he.ts b/translations/ring_client_windows_he.ts new file mode 100644 index 00000000..b4596283 --- /dev/null +++ b/translations/ring_client_windows_he.ts @@ -0,0 +1,1589 @@ + + + AboutDialog + + + + About + אודות + + + + about button + + + + + credits button + + + + + Credits + תודות + + + + Free as in Freedom + + + + + The Microsoft Windows client for Jami. +Jami is a secured and distributed communication software. + + + + + version + גירסה + + + + Created by: + + + + + Artwork by: + + + + + Based on the SFLPhone project + מבוסס על הפרויקט SFLPhone + + + + AccountItemDelegate + + + Add Account + + + + + AdvancedSIPSettingsWidget + + + Form + + + + + Call Settings + + + + + Auto Answer Calls + + + + + Enable Custom Ringtone + + + + + Connectivity + + + + + STUN Address + + + + + Use STUN + + + + + Use UPnP + + + + + Use TURN + + + + + TURN Password + + + + + TURN Username + + + + + TURN Address + + + + + Media + מדיה + + + + Enable Video + אפשר וידאו + + + + Video Codecs + + + + + Audio Codecs + + + + + Audio Files (*.wav *.ogg *.opus *.mp3 *aiff *wma) + + + + + Add a custom ringtone + + + + + AdvancedSettingsWidget + + + Form + + + + + Call Settings + + + + + Allow Calls From Untrusted Peers + + + + + Auto Answer Calls + + + + + Enable Custom Ringtone + + + + + Add a custom ringtone + + + + + Name Server + + + + + Address + כתובת + + + + OpenDHT Configuration + + + + + Enable Proxy + + + + + Bootstrap + + + + + Security + אבטחה + + + + Private Key Password + סיסמת מפתח פרטי + + + + User Certificate + + + + + Private Key + + + + + CA Certificate + + + + + Connectivity + + + + + Use STUN + + + + + STUN Address + + + + + Use UPnP + + + + + Use TURN + + + + + TURN Password + + + + + TURN Username + + + + + TURN Address + + + + + Media + מדיה + + + + Enable Video + אפשר וידאו + + + + Audio Codecs + + + + + Video Codecs + + + + + Audio Files (*.wav *.ogg *.opus *.mp3 *aiff *wma) + + + + + AnimatedOverlay + + + Form + + + + + BannedItemWidget + + + Form + + + + + name + + + + + id + + + + + CallWidget + + + Show conversations + + + + + Conversations + דיונים + + + + Search contact text input + + + + + Jami is free software for universal communication which respects the freedoms and privacy of its users. + + + + + + This is your ID. +Copy and share it with your friends! + + + + + + Show ring ID QR code + + + + + Share ring ID button + + + + + Double-click to copy + + + + + Error while generating QR Code + + + + + + best name + + + + + best Id + + + + + Back to homepage button + + + + + Add to contacts + + + + + Show invites + + + + + Invites + + + + + + Find a new or existing contact + + + + + Wants to talk to you! + + + + + Answer incoming call button + + + + + Ignore incoming call button + + + + + Answer + + + + + Ignore + + + + + Cancel outgoing call + + + + + Cancel + ביטול + + + + Start video call + + + + + Start audio call + + + + + Clear conversation + + + + + Remove contact + + + + + Block contact + + + + + Copy number + העתק מספר + + + + Search your received invitations + + + + + Contact me on Jami + + + + + My Id is : + + + + + %1 + %1 is the contact username + + + + + %1 + %1 is the contact unique identifier + + + + + Call incoming from %1 + + + + + DeleteAccountDialog + + + Account deletion + + + + + Do you really want to delete the following account? + + + + + If this account hasn't been exported, or added to another device, it will be irrevocably lost. + + + + + Permanently delete account + + + + + Delete + מחק + + + + Cancel account deletion + + + + + Cancel + ביטול + + + + DeviceItemWidget + + + Form + + + + + Device Id + + + + + this device + + + + + InviteButtonsWidget + + + Accept + קבל + + + + Refuse + סרב + + + + Block + חסום + + + + LinkDeviceDialog + + + Dialog + דו שיח + + + + Enter your account password + + + + + Password + סיסמה + + + + Ok + + + + + Cancel + ביטול + + + + Exporting account + + + + + Your PIN is + + + + + PIN + + + + + This pin and the account password should be entered in your device within 10 minutes. + + + + + Close + + + + + Link Another Device + + + + + Incorrect password + + + + + Something went wrong. +Please try again later. + + + + + MainWindow + + + Settings + הגדרות + + + + Exit + + + + + About + אודות + + + + Jami + + + + + NameRegistrationDialog + + + Set Registered Name + + + + + Enter your account password + + + + + Password text input + + + + + Password text entry + + + + + Password + סיסמה + + + + Register + הירשם + + + + Cancel + ביטול + + + + Registering Name + + + + + Something went wrong + + + + + Close + + + + + Incorrect password + + + + + Network error + + + + + NewWizardWidget + + + Form + + + + + Welcome Label + + + + + Welcome to + + + + + Welcome Logo + + + + + Create Jami account button + + + + + Push button for Jami account creation start trigger + + + + + Create a Jami account + + + + + Link device button + + + + + Push button for device linkage start trigger + + + + + Link this device to an account + + + + + Create Jami SIP account button + + + + + Push button for Jami SIP account creation start trigger + + + + + Create a SIP account + + + + + Link this device to an existing account + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Ubuntu'; font-size:14px; color:#555555;">To link this device to another account, you first </span><span style=" font-family:'Ubuntu'; font-size:14px; font-weight:600; color:#555555;">need to obtain a PIN</span><span style=" font-family:'Ubuntu'; font-size:14px; color:#555555;"> code. To generate the PIN code:</span></p> +<ol style="margin-top: 0px; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; -qt-list-indent: 1;"><li style=" font-family:'Ubuntu'; font-size:14px; color:#555555;" style=" margin-top:12px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:14px;">Go to the </span><span style=" font-size:14px; font-weight:600;">Account management setting</span><span style=" font-size:14px;"> of a previous device</span></li> +<li style=" font-family:'Ubuntu'; font-size:14px; color:#555555;" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:14px;">Choose the </span><span style=" font-size:14px; font-weight:600;">Jami account</span><span style=" font-size:14px;"> you want to use</span></li> +<li style=" font-family:'Ubuntu'; font-size:14px; color:#555555;" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:14px;">Go to the </span><span style=" font-size:14px; font-weight:600;">Devices</span><span style=" font-size:14px;"> tab</span></li> +<li style=" font-family:'Ubuntu'; font-size:14px; color:#555555;" style=" margin-top:0px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:14px;">Select </span><span style=" font-size:14px; font-weight:600;">Add a device</span></li></ol> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Ubuntu'; font-size:14px; color:#555555;">You will get the necessary PIN to complete this form. The PIN is only valid for </span><span style=" font-family:'Ubuntu'; font-size:14px; font-weight:600; color:#555555;">10 minutes</span><span style=" font-family:'Ubuntu'; font-size:10px; color:#555555;">.</span></p></body></html> + + + + + Enter your pin: + + + + + Or import a file: + + + + + Link from exported account archive file + + + + + + + (None) + + + + + Password: + + + + + + Profile + פרופיל + + + + + Profile name + + + + + Account + חשבון + + + + Register your username. +This will reserve the username so that only you can use it. +Your friends will be able to call you with your usename +instead of using your ID. + + + + + Public username checkbox + + + + + Checkbox selecting if the user wants a public username + + + + + Register public username + + + + + Public username edit + + + + + Choose your username + + + + + Password text input + + + + + Password text entry + + + + + + Password + סיסמה + + + + + Password confirmation text input + + + + + Confirm password + + + + + SIP Account + חשבון SIP + + + + SIP Server edit + + + + + Server + + + + + SIP proxy input + + + + + SIP proxy text entry + + + + + Proxy + פרוקסי + + + + SIP username input + + + + + SIP Password text entry + + + + + Username + שם משתמש + + + + + SIP Password text input + + + + + Generating your Jami account… + + + + + Previous page button + + + + + push button to access previous page of wizard + + + + + Previous + + + + + Cancel account create/link + + + + + push button to cancel account creation or linking + + + + + Back + + + + + Next page Button + + + + + Push button to access next page of wizard + + + + + Next + קדימה + + + + Open File + + + + + Jami archive files (*.gz); All files (*) + + + + + Your account needs to be migrated. Enter your password. + + + + + Migrating your Jami account... + + + + + Importing account archive... + + + + + Generating your Jami account... + + + + + Generating your SIP account... + + + + + Error creating account + + + + + PasswordDialog + + + Change Account Password + + + + + Enter Current Password + + + + + Enter New Password + + + + + Confirm New Password + + + + + Confirm + + + + + Cancel + ביטול + + + + Current Password Incorrect + + + + + PhotoBoothDialog + + + Photobooth + + + + + PhotoboothWidget + + + Form + + + + + Photobooth display + + + + + Choose File + בחר קובץ + + + + Image Files (*.jpg *.jpeg *.png) + + + + + PrivateBridging + + + Choose File + בחר קובץ + + + + Files (*) + קבצים (*) + + + + QObject + + + No default mail client found + + + + + + Edit Device Name + + + + + Unlink Device From Account + + + + + Save new device name + + + + + Add as contact + + + + + RingButton + + + Select folder + + + + + SettingsWidget + + + Form + + + + + Settings + הגדרות + + + + Account + חשבון + + + + + General + כלליות + + + + + Audio / Video + + + + + System + + + + + Enable desktop notifications + + + + + Keep minimized on close + + + + + Download folder + + + + + Save in + + + + + Always Recording + + + + + Updates + + + + + Check for updates automatically every + + + + + Interval between update checks in days selector + + + + + days + + + + + Check for updates now button + + + + + Check for updates now + + + + + Password + סיסמה + + + + + Enable + + + + + toggle enable notifications + + + + + Toggle keep minimized on close + + + + + Call Recordings + + + + + Toggle automatic updates + + + + + Jami Account + + + + + + Profile + פרופיל + + + + + Identity + + + + + Id + + + + + Registered name + + + + + Type here to register a username + + + + + Register + הירשם + + + + Change Password + + + + + Export Account + + + + + + Delete Account + + + + + Linked Devices + + + + + Link Another Device + + + + + Banned Contacts + + + + + Format + + + + + Video device framerate selector + + + + + Preview unavailable + + + + + + Advanced Account Settings + + + + + SIP Account + חשבון SIP + + + + Username + שם משתמש + + + + Hostname + שם מארח + + + + Proxy + פרוקסי + + + + Audio + אודיו + + + + Microphone + + + + + Audio input device selector + + + + + Output Device + + + + + Choose the output device + + + + + Video + וידאו + + + + Device + מכשיר + + + + Video device selector + + + + + A registered name should not have any spaces and must be at least three letters long + + + + + This name is already taken + + + + + + Enter an alias + + + + + Register this name + + + + + Remove Device + + + + + Enter this account's password to confirm the removal of this device + + + + + Are you sure you wish to remove this device? + + + + + Export Account Here + + + + + Select A Folder For Your Downloads + + + + + Select A Folder For Your Recordings + + + + + VideoOverlay + + + Call on Hold + + + + + Hold / Unhold + + + + + Chat + שיחה + + + + Mute Mic + + + + + Record call + + + + + Name label + + + + + Time elapsed + + + + + 00:00 + + + + + Hangup + נתק + + + + Mute Video + כבה וידאו + + + + VideoView + + + Share entire screen + + + + + Share screen area + שתף אזור מסך + + + + Share file + שתף קובץ + + + \ No newline at end of file diff --git a/translations/ring_client_windows_hi_IN.ts b/translations/ring_client_windows_hi_IN.ts new file mode 100644 index 00000000..dab0d6f4 --- /dev/null +++ b/translations/ring_client_windows_hi_IN.ts @@ -0,0 +1,1589 @@ + + + AboutDialog + + + + About + + + + + about button + + + + + credits button + + + + + Credits + + + + + Free as in Freedom + + + + + The Microsoft Windows client for Jami. +Jami is a secured and distributed communication software. + + + + + version + + + + + Created by: + + + + + Artwork by: + + + + + Based on the SFLPhone project + + + + + AccountItemDelegate + + + Add Account + + + + + AdvancedSIPSettingsWidget + + + Form + + + + + Call Settings + + + + + Auto Answer Calls + + + + + Enable Custom Ringtone + + + + + Connectivity + + + + + STUN Address + + + + + Use STUN + + + + + Use UPnP + + + + + Use TURN + + + + + TURN Password + + + + + TURN Username + + + + + TURN Address + + + + + Media + + + + + Enable Video + + + + + Video Codecs + + + + + Audio Codecs + + + + + Audio Files (*.wav *.ogg *.opus *.mp3 *aiff *wma) + + + + + Add a custom ringtone + + + + + AdvancedSettingsWidget + + + Form + + + + + Call Settings + + + + + Allow Calls From Untrusted Peers + + + + + Auto Answer Calls + + + + + Enable Custom Ringtone + + + + + Add a custom ringtone + + + + + Name Server + + + + + Address + + + + + OpenDHT Configuration + + + + + Enable Proxy + + + + + Bootstrap + + + + + Security + + + + + Private Key Password + + + + + User Certificate + + + + + Private Key + + + + + CA Certificate + + + + + Connectivity + + + + + Use STUN + + + + + STUN Address + + + + + Use UPnP + + + + + Use TURN + + + + + TURN Password + + + + + TURN Username + + + + + TURN Address + + + + + Media + + + + + Enable Video + + + + + Audio Codecs + + + + + Video Codecs + + + + + Audio Files (*.wav *.ogg *.opus *.mp3 *aiff *wma) + + + + + AnimatedOverlay + + + Form + + + + + BannedItemWidget + + + Form + + + + + name + + + + + id + + + + + CallWidget + + + Show conversations + + + + + Conversations + + + + + Search contact text input + + + + + Jami is free software for universal communication which respects the freedoms and privacy of its users. + + + + + + This is your ID. +Copy and share it with your friends! + + + + + + Show ring ID QR code + + + + + Share ring ID button + + + + + Double-click to copy + + + + + Error while generating QR Code + + + + + + best name + + + + + best Id + + + + + Back to homepage button + + + + + Add to contacts + + + + + Show invites + + + + + Invites + + + + + + Find a new or existing contact + + + + + Wants to talk to you! + + + + + Answer incoming call button + + + + + Ignore incoming call button + + + + + Answer + + + + + Ignore + + + + + Cancel outgoing call + + + + + Cancel + + + + + Start video call + + + + + Start audio call + + + + + Clear conversation + + + + + Remove contact + + + + + Block contact + + + + + Copy number + + + + + Search your received invitations + + + + + Contact me on Jami + + + + + My Id is : + + + + + %1 + %1 is the contact username + + + + + %1 + %1 is the contact unique identifier + + + + + Call incoming from %1 + + + + + DeleteAccountDialog + + + Account deletion + + + + + Do you really want to delete the following account? + + + + + If this account hasn't been exported, or added to another device, it will be irrevocably lost. + + + + + Permanently delete account + + + + + Delete + + + + + Cancel account deletion + + + + + Cancel + + + + + DeviceItemWidget + + + Form + + + + + Device Id + + + + + this device + + + + + InviteButtonsWidget + + + Accept + + + + + Refuse + + + + + Block + + + + + LinkDeviceDialog + + + Dialog + + + + + Enter your account password + + + + + Password + + + + + Ok + + + + + Cancel + + + + + Exporting account + + + + + Your PIN is + + + + + PIN + + + + + This pin and the account password should be entered in your device within 10 minutes. + + + + + Close + + + + + Link Another Device + + + + + Incorrect password + + + + + Something went wrong. +Please try again later. + + + + + MainWindow + + + Settings + + + + + Exit + + + + + About + + + + + Jami + + + + + NameRegistrationDialog + + + Set Registered Name + + + + + Enter your account password + + + + + Password text input + + + + + Password text entry + + + + + Password + + + + + Register + + + + + Cancel + + + + + Registering Name + + + + + Something went wrong + + + + + Close + + + + + Incorrect password + + + + + Network error + + + + + NewWizardWidget + + + Form + + + + + Welcome Label + + + + + Welcome to + + + + + Welcome Logo + + + + + Create Jami account button + + + + + Push button for Jami account creation start trigger + + + + + Create a Jami account + + + + + Link device button + + + + + Push button for device linkage start trigger + + + + + Link this device to an account + + + + + Create Jami SIP account button + + + + + Push button for Jami SIP account creation start trigger + + + + + Create a SIP account + + + + + Link this device to an existing account + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Ubuntu'; font-size:14px; color:#555555;">To link this device to another account, you first </span><span style=" font-family:'Ubuntu'; font-size:14px; font-weight:600; color:#555555;">need to obtain a PIN</span><span style=" font-family:'Ubuntu'; font-size:14px; color:#555555;"> code. To generate the PIN code:</span></p> +<ol style="margin-top: 0px; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; -qt-list-indent: 1;"><li style=" font-family:'Ubuntu'; font-size:14px; color:#555555;" style=" margin-top:12px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:14px;">Go to the </span><span style=" font-size:14px; font-weight:600;">Account management setting</span><span style=" font-size:14px;"> of a previous device</span></li> +<li style=" font-family:'Ubuntu'; font-size:14px; color:#555555;" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:14px;">Choose the </span><span style=" font-size:14px; font-weight:600;">Jami account</span><span style=" font-size:14px;"> you want to use</span></li> +<li style=" font-family:'Ubuntu'; font-size:14px; color:#555555;" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:14px;">Go to the </span><span style=" font-size:14px; font-weight:600;">Devices</span><span style=" font-size:14px;"> tab</span></li> +<li style=" font-family:'Ubuntu'; font-size:14px; color:#555555;" style=" margin-top:0px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:14px;">Select </span><span style=" font-size:14px; font-weight:600;">Add a device</span></li></ol> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Ubuntu'; font-size:14px; color:#555555;">You will get the necessary PIN to complete this form. The PIN is only valid for </span><span style=" font-family:'Ubuntu'; font-size:14px; font-weight:600; color:#555555;">10 minutes</span><span style=" font-family:'Ubuntu'; font-size:10px; color:#555555;">.</span></p></body></html> + + + + + Enter your pin: + + + + + Or import a file: + + + + + Link from exported account archive file + + + + + + + (None) + + + + + Password: + + + + + + Profile + + + + + + Profile name + + + + + Account + खाता + + + + Register your username. +This will reserve the username so that only you can use it. +Your friends will be able to call you with your usename +instead of using your ID. + + + + + Public username checkbox + + + + + Checkbox selecting if the user wants a public username + + + + + Register public username + + + + + Public username edit + + + + + Choose your username + + + + + Password text input + + + + + Password text entry + + + + + + Password + + + + + + Password confirmation text input + + + + + Confirm password + + + + + SIP Account + + + + + SIP Server edit + + + + + Server + + + + + SIP proxy input + + + + + SIP proxy text entry + + + + + Proxy + + + + + SIP username input + + + + + SIP Password text entry + + + + + Username + + + + + + SIP Password text input + + + + + Generating your Jami account… + + + + + Previous page button + + + + + push button to access previous page of wizard + + + + + Previous + + + + + Cancel account create/link + + + + + push button to cancel account creation or linking + + + + + Back + + + + + Next page Button + + + + + Push button to access next page of wizard + + + + + Next + + + + + Open File + + + + + Jami archive files (*.gz); All files (*) + + + + + Your account needs to be migrated. Enter your password. + + + + + Migrating your Jami account... + + + + + Importing account archive... + + + + + Generating your Jami account... + + + + + Generating your SIP account... + + + + + Error creating account + + + + + PasswordDialog + + + Change Account Password + + + + + Enter Current Password + + + + + Enter New Password + + + + + Confirm New Password + + + + + Confirm + + + + + Cancel + + + + + Current Password Incorrect + + + + + PhotoBoothDialog + + + Photobooth + + + + + PhotoboothWidget + + + Form + + + + + Photobooth display + + + + + Choose File + + + + + Image Files (*.jpg *.jpeg *.png) + + + + + PrivateBridging + + + Choose File + + + + + Files (*) + + + + + QObject + + + No default mail client found + + + + + + Edit Device Name + + + + + Unlink Device From Account + + + + + Save new device name + + + + + Add as contact + + + + + RingButton + + + Select folder + + + + + SettingsWidget + + + Form + + + + + Settings + + + + + Account + खाता + + + + + General + + + + + + Audio / Video + + + + + System + + + + + Enable desktop notifications + + + + + Keep minimized on close + + + + + Download folder + + + + + Save in + + + + + Always Recording + + + + + Updates + + + + + Check for updates automatically every + + + + + Interval between update checks in days selector + + + + + days + + + + + Check for updates now button + + + + + Check for updates now + + + + + Password + + + + + + Enable + + + + + toggle enable notifications + + + + + Toggle keep minimized on close + + + + + Call Recordings + + + + + Toggle automatic updates + + + + + Jami Account + + + + + + Profile + + + + + + Identity + + + + + Id + + + + + Registered name + + + + + Type here to register a username + + + + + Register + + + + + Change Password + + + + + Export Account + + + + + + Delete Account + + + + + Linked Devices + + + + + Link Another Device + + + + + Banned Contacts + + + + + Format + + + + + Video device framerate selector + + + + + Preview unavailable + + + + + + Advanced Account Settings + + + + + SIP Account + + + + + Username + + + + + Hostname + + + + + Proxy + + + + + Audio + आॅडियो + + + + Microphone + + + + + Audio input device selector + + + + + Output Device + + + + + Choose the output device + + + + + Video + वीडियो + + + + Device + + + + + Video device selector + + + + + A registered name should not have any spaces and must be at least three letters long + + + + + This name is already taken + + + + + + Enter an alias + + + + + Register this name + + + + + Remove Device + + + + + Enter this account's password to confirm the removal of this device + + + + + Are you sure you wish to remove this device? + + + + + Export Account Here + + + + + Select A Folder For Your Downloads + + + + + Select A Folder For Your Recordings + + + + + VideoOverlay + + + Call on Hold + + + + + Hold / Unhold + + + + + Chat + + + + + Mute Mic + + + + + Record call + + + + + Name label + + + + + Time elapsed + + + + + 00:00 + + + + + Hangup + + + + + Mute Video + + + + + VideoView + + + Share entire screen + + + + + Share screen area + + + + + Share file + + + + \ No newline at end of file diff --git a/translations/ring_client_windows_hr.ts b/translations/ring_client_windows_hr.ts new file mode 100644 index 00000000..8aa78ba0 --- /dev/null +++ b/translations/ring_client_windows_hr.ts @@ -0,0 +1,1589 @@ + + + AboutDialog + + + + About + O programu + + + + about button + + + + + credits button + + + + + Credits + Zasluge + + + + Free as in Freedom + + + + + The Microsoft Windows client for Jami. +Jami is a secured and distributed communication software. + + + + + version + verzija + + + + Created by: + Napravio: + + + + Artwork by: + + + + + Based on the SFLPhone project + Bazirano na SFLPhone projektu + + + + AccountItemDelegate + + + Add Account + + + + + AdvancedSIPSettingsWidget + + + Form + + + + + Call Settings + + + + + Auto Answer Calls + + + + + Enable Custom Ringtone + + + + + Connectivity + Spojivost + + + + STUN Address + + + + + Use STUN + Koristi STUN + + + + Use UPnP + + + + + Use TURN + Koristi TURN + + + + TURN Password + + + + + TURN Username + + + + + TURN Address + + + + + Media + Medij + + + + Enable Video + Omogući video + + + + Video Codecs + + + + + Audio Codecs + + + + + Audio Files (*.wav *.ogg *.opus *.mp3 *aiff *wma) + + + + + Add a custom ringtone + + + + + AdvancedSettingsWidget + + + Form + + + + + Call Settings + + + + + Allow Calls From Untrusted Peers + + + + + Auto Answer Calls + + + + + Enable Custom Ringtone + + + + + Add a custom ringtone + + + + + Name Server + + + + + Address + Adresa + + + + OpenDHT Configuration + + + + + Enable Proxy + + + + + Bootstrap + + + + + Security + Sigurnost + + + + Private Key Password + Lozinka privatnog ključa + + + + User Certificate + Korisnički certifikat + + + + Private Key + + + + + CA Certificate + + + + + Connectivity + Spojivost + + + + Use STUN + Koristi STUN + + + + STUN Address + + + + + Use UPnP + + + + + Use TURN + Koristi TURN + + + + TURN Password + + + + + TURN Username + + + + + TURN Address + + + + + Media + Medij + + + + Enable Video + Omogući video + + + + Audio Codecs + + + + + Video Codecs + + + + + Audio Files (*.wav *.ogg *.opus *.mp3 *aiff *wma) + + + + + AnimatedOverlay + + + Form + + + + + BannedItemWidget + + + Form + + + + + name + + + + + id + + + + + CallWidget + + + Show conversations + + + + + Conversations + Razgovori + + + + Search contact text input + + + + + Jami is free software for universal communication which respects the freedoms and privacy of its users. + Jami je slobodni software za univerzalnu komunikaciju koji poštuje slobode i privatnost svojih korisnika. + + + + + This is your ID. +Copy and share it with your friends! + + + + + + Show ring ID QR code + + + + + Share ring ID button + + + + + Double-click to copy + + + + + Error while generating QR Code + Greška prilikom generiranja QR koda + + + + + best name + + + + + best Id + + + + + Back to homepage button + + + + + Add to contacts + Dodaj u kontakte + + + + Show invites + + + + + Invites + + + + + + Find a new or existing contact + + + + + Wants to talk to you! + Želi govoriti sa vama! + + + + Answer incoming call button + + + + + Ignore incoming call button + + + + + Answer + Javi se + + + + Ignore + Ignoriraj + + + + Cancel outgoing call + + + + + Cancel + Poništi + + + + Start video call + + + + + Start audio call + + + + + Clear conversation + + + + + Remove contact + + + + + Block contact + Blokiraj kontakt + + + + Copy number + Kopiraj broj + + + + Search your received invitations + + + + + Contact me on Jami + + + + + My Id is : + + + + + %1 + %1 is the contact username + %1 + + + + %1 + %1 is the contact unique identifier + %1 + + + + Call incoming from %1 + Dolazni poziv od %1 + + + + DeleteAccountDialog + + + Account deletion + + + + + Do you really want to delete the following account? + + + + + If this account hasn't been exported, or added to another device, it will be irrevocably lost. + + + + + Permanently delete account + + + + + Delete + Izbriši + + + + Cancel account deletion + + + + + Cancel + Poništi + + + + DeviceItemWidget + + + Form + + + + + Device Id + + + + + this device + + + + + InviteButtonsWidget + + + Accept + Prihvati + + + + Refuse + Odbij + + + + Block + Blokiraj + + + + LinkDeviceDialog + + + Dialog + Dijalog + + + + Enter your account password + + + + + Password + Lozinka + + + + Ok + U redu + + + + Cancel + Poništi + + + + Exporting account + izvozim račun + + + + Your PIN is + + + + + PIN + PIN + + + + This pin and the account password should be entered in your device within 10 minutes. + + + + + Close + + + + + Link Another Device + + + + + Incorrect password + + + + + Something went wrong. +Please try again later. + + + + + MainWindow + + + Settings + Postavke + + + + Exit + Izađi + + + + About + O programu + + + + Jami + + + + + NameRegistrationDialog + + + Set Registered Name + + + + + Enter your account password + + + + + Password text input + + + + + Password text entry + + + + + Password + Lozinka + + + + Register + Registriraj + + + + Cancel + Poništi + + + + Registering Name + + + + + Something went wrong + + + + + Close + + + + + Incorrect password + + + + + Network error + Greška mreže + + + + NewWizardWidget + + + Form + + + + + Welcome Label + + + + + Welcome to + + + + + Welcome Logo + + + + + Create Jami account button + + + + + Push button for Jami account creation start trigger + + + + + Create a Jami account + Napravite Jami račun + + + + Link device button + + + + + Push button for device linkage start trigger + + + + + Link this device to an account + Povežite ovaj uređaj s računom + + + + Create Jami SIP account button + + + + + Push button for Jami SIP account creation start trigger + + + + + Create a SIP account + + + + + Link this device to an existing account + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Ubuntu'; font-size:14px; color:#555555;">To link this device to another account, you first </span><span style=" font-family:'Ubuntu'; font-size:14px; font-weight:600; color:#555555;">need to obtain a PIN</span><span style=" font-family:'Ubuntu'; font-size:14px; color:#555555;"> code. To generate the PIN code:</span></p> +<ol style="margin-top: 0px; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; -qt-list-indent: 1;"><li style=" font-family:'Ubuntu'; font-size:14px; color:#555555;" style=" margin-top:12px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:14px;">Go to the </span><span style=" font-size:14px; font-weight:600;">Account management setting</span><span style=" font-size:14px;"> of a previous device</span></li> +<li style=" font-family:'Ubuntu'; font-size:14px; color:#555555;" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:14px;">Choose the </span><span style=" font-size:14px; font-weight:600;">Jami account</span><span style=" font-size:14px;"> you want to use</span></li> +<li style=" font-family:'Ubuntu'; font-size:14px; color:#555555;" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:14px;">Go to the </span><span style=" font-size:14px; font-weight:600;">Devices</span><span style=" font-size:14px;"> tab</span></li> +<li style=" font-family:'Ubuntu'; font-size:14px; color:#555555;" style=" margin-top:0px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:14px;">Select </span><span style=" font-size:14px; font-weight:600;">Add a device</span></li></ol> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Ubuntu'; font-size:14px; color:#555555;">You will get the necessary PIN to complete this form. The PIN is only valid for </span><span style=" font-family:'Ubuntu'; font-size:14px; font-weight:600; color:#555555;">10 minutes</span><span style=" font-family:'Ubuntu'; font-size:10px; color:#555555;">.</span></p></body></html> + + + + + Enter your pin: + + + + + Or import a file: + + + + + Link from exported account archive file + + + + + + + (None) + + + + + Password: + Lozinka: + + + + + Profile + Profil + + + + + Profile name + + + + + Account + Račun + + + + Register your username. +This will reserve the username so that only you can use it. +Your friends will be able to call you with your usename +instead of using your ID. + + + + + Public username checkbox + + + + + Checkbox selecting if the user wants a public username + + + + + Register public username + + + + + Public username edit + + + + + Choose your username + Izaberite vaše korisničko ime + + + + Password text input + + + + + Password text entry + + + + + + Password + Lozinka + + + + + Password confirmation text input + + + + + Confirm password + Potvrdi lozinku + + + + SIP Account + SIP račun + + + + SIP Server edit + + + + + Server + + + + + SIP proxy input + + + + + SIP proxy text entry + + + + + Proxy + Proxy + + + + SIP username input + + + + + SIP Password text entry + + + + + Username + Korisničko ime + + + + + SIP Password text input + + + + + Generating your Jami account… + + + + + Previous page button + + + + + push button to access previous page of wizard + + + + + Previous + + + + + Cancel account create/link + + + + + push button to cancel account creation or linking + + + + + Back + Natrag + + + + Next page Button + + + + + Push button to access next page of wizard + + + + + Next + Slijedeće + + + + Open File + Otvori datoteku + + + + Jami archive files (*.gz); All files (*) + + + + + Your account needs to be migrated. Enter your password. + + + + + Migrating your Jami account... + + + + + Importing account archive... + + + + + Generating your Jami account... + + + + + Generating your SIP account... + + + + + Error creating account + + + + + PasswordDialog + + + Change Account Password + + + + + Enter Current Password + + + + + Enter New Password + + + + + Confirm New Password + + + + + Confirm + + + + + Cancel + Poništi + + + + Current Password Incorrect + + + + + PhotoBoothDialog + + + Photobooth + + + + + PhotoboothWidget + + + Form + + + + + Photobooth display + + + + + Choose File + Izaberite datoteku + + + + Image Files (*.jpg *.jpeg *.png) + + + + + PrivateBridging + + + Choose File + Izaberite datoteku + + + + Files (*) + Datoteke (*) + + + + QObject + + + No default mail client found + + + + + + Edit Device Name + + + + + Unlink Device From Account + + + + + Save new device name + + + + + Add as contact + + + + + RingButton + + + Select folder + + + + + SettingsWidget + + + Form + + + + + Settings + Postavke + + + + Account + Račun + + + + + General + Opće + + + + + Audio / Video + + + + + System + Sustav + + + + Enable desktop notifications + + + + + Keep minimized on close + + + + + Download folder + + + + + Save in + Spremi u + + + + Always Recording + + + + + Updates + + + + + Check for updates automatically every + + + + + Interval between update checks in days selector + + + + + days + + + + + Check for updates now button + + + + + Check for updates now + + + + + Password + Lozinka + + + + + Enable + + + + + toggle enable notifications + + + + + Toggle keep minimized on close + + + + + Call Recordings + + + + + Toggle automatic updates + + + + + Jami Account + + + + + + Profile + Profil + + + + + Identity + + + + + Id + + + + + Registered name + + + + + Type here to register a username + + + + + Register + Registriraj + + + + Change Password + + + + + Export Account + + + + + + Delete Account + + + + + Linked Devices + + + + + Link Another Device + + + + + Banned Contacts + + + + + Format + + + + + Video device framerate selector + + + + + Preview unavailable + + + + + + Advanced Account Settings + + + + + SIP Account + SIP račun + + + + Username + Korisničko ime + + + + Hostname + Ime poslužitelja + + + + Proxy + Proxy + + + + Audio + Zvuk + + + + Microphone + + + + + Audio input device selector + + + + + Output Device + Izlazni uređaj + + + + Choose the output device + + + + + Video + Video + + + + Device + Uređaj + + + + Video device selector + + + + + A registered name should not have any spaces and must be at least three letters long + + + + + This name is already taken + + + + + + Enter an alias + + + + + Register this name + + + + + Remove Device + + + + + Enter this account's password to confirm the removal of this device + + + + + Are you sure you wish to remove this device? + + + + + Export Account Here + + + + + Select A Folder For Your Downloads + + + + + Select A Folder For Your Recordings + + + + + VideoOverlay + + + Call on Hold + + + + + Hold / Unhold + + + + + Chat + Čavrljanje + + + + Mute Mic + Isključi mikrofon + + + + Record call + + + + + Name label + + + + + Time elapsed + + + + + 00:00 + 00:00 + + + + Hangup + + + + + Mute Video + Ugasi video + + + + VideoView + + + Share entire screen + + + + + Share screen area + Dijelite područje zaslona + + + + Share file + Dijeli datoteku + + + \ No newline at end of file diff --git a/translations/ring_client_windows_hu.ts b/translations/ring_client_windows_hu.ts new file mode 100644 index 00000000..6774d349 --- /dev/null +++ b/translations/ring_client_windows_hu.ts @@ -0,0 +1,1604 @@ + + + AboutDialog + + + + About + Névjegy + + + + about button + Névjegye gombja + + + + credits button + Közreműködők gombja + + + + Credits + Készítők + + + + Free as in Freedom + Szabad, mint a szabadság + + + + The Microsoft Windows client for Jami. +Jami is a secured and distributed communication software. + A Microsoft Windows ügyfél a Jamihoz. +A Jami egy biztonságos és osztott csevegőprogram. + + + + version + verzió + + + + Created by: + Szerző: + + + + Artwork by: + Művészi elemek készítője: + + + + Based on the SFLPhone project + Az SFLPhone termék alapján + + + + AccountItemDelegate + + + Add Account + Fiók hozzáadása + + + + AdvancedSIPSettingsWidget + + + Form + Feladó + + + + Call Settings + Hívás beállítások + + + + Auto Answer Calls + Hívások önműködő fogadása + + + + Enable Custom Ringtone + Egyéni csengőhang engedélyezése + + + + Connectivity + Kapcsolódás + + + + STUN Address + STUN cím + + + + Use STUN + STUN használata + + + + Use UPnP + UPnP használata + + + + Use TURN + TURN használata + + + + TURN Password + TURN jelszó + + + + TURN Username + TURN felhasználónév + + + + TURN Address + TURN cím + + + + Media + Média + + + + Enable Video + Videó engedélyezése + + + + Video Codecs + Videókodekek + + + + Audio Codecs + Hangkodekek + + + + Audio Files (*.wav *.ogg *.opus *.mp3 *aiff *wma) + Hangfájlok (*aiff *.mp3 *.ogg *.opus *.wav *wma) + + + + Add a custom ringtone + Egyéni csengőhang hozzáadása + + + + AdvancedSettingsWidget + + + Form + Feladó + + + + Call Settings + Hívás beállítások + + + + Allow Calls From Untrusted Peers + Hívások engedélyezése ismeretlen kapcsolatoktól + + + + Auto Answer Calls + Hívások önműködő fogadása + + + + Enable Custom Ringtone + Egyéni csengőhang engedélyezése + + + + Add a custom ringtone + Egyéni csengőhang hozzáadása + + + + Name Server + Kiszolgálói néve + + + + Address + Cím + + + + OpenDHT Configuration + OpenDHT beállítások + + + + Enable Proxy + Meghatalmazott engedélyezése + + + + Bootstrap + Bootstrap + + + + Security + Biztonság + + + + Private Key Password + Személyes kulcs jelszava + + + + User Certificate + Felhasználói tanúsítvány + + + + Private Key + Személyes kulcs + + + + CA Certificate + CA tanúsítvány + + + + Connectivity + Kapcsolódás + + + + Use STUN + STUN használata + + + + STUN Address + STUN cím + + + + Use UPnP + UPnP használata + + + + Use TURN + TURN használata + + + + TURN Password + TURN jelszó + + + + TURN Username + TURN felhasználónév + + + + TURN Address + TURN cím + + + + Media + Média + + + + Enable Video + Videó engedélyezése + + + + Audio Codecs + Hangkodekek + + + + Video Codecs + Videókodekek + + + + Audio Files (*.wav *.ogg *.opus *.mp3 *aiff *wma) + Hangfájlok (*aiff *.mp3 *.ogg *.opus *.wav *wma) + + + + AnimatedOverlay + + + Form + Feladó + + + + BannedItemWidget + + + Form + Feladó + + + + name + név + + + + id + Azonosító + + + + CallWidget + + + Show conversations + Beszélgetések megjelenítése + + + + Conversations + Beszélgetések + + + + Search contact text input + Keresés kapcsolati szövegbevitel + + + + Jami is free software for universal communication which respects the freedoms and privacy of its users. + A Jami (GNU csomag, korábban Ring) egy univerzális és elosztott közlés emelvény, amely tiszteletben tartja a felhasználók szabadságait és magánéletét. + + + + + This is your ID. +Copy and share it with your friends! + + +Ez az Ön azonosítója. +Másolja és ossza meg a barátaival! + + + + Show ring ID QR code + Jami azonosító QR-kód mutatása + + + + Share ring ID button + Ring azonosító megosztó gomb + + + + Double-click to copy + Kattintson duplán a másolásra + + + + Error while generating QR Code + Hiba a QR-kód generálása közben + + + + + best name + legjobb név + + + + best Id + legjobb azonosító + + + + Back to homepage button + Vissza a főoldalra gomb + + + + Add to contacts + Hozzáadás a kapcsolatokhoz + + + + Show invites + Meghívók megjelenítése + + + + Invites + Meghívók + + + + + Find a new or existing contact + Keressen új vagy meglévő kapcsolatot + + + + Wants to talk to you! + Beszélni akar önnel! + + + + Answer incoming call button + Bejövő hívás fogadása gomb + + + + Ignore incoming call button + Bejövő hívás figyelmen kívül hagyása gomb + + + + Answer + Válaszol + + + + Ignore + Figyelmen kívül hagy + + + + Cancel outgoing call + Kimenő hívás visszavonása + + + + Cancel + Mégse + + + + Start video call + Videóhívás indítása + + + + Start audio call + Hanghívás indítása + + + + Clear conversation + Beszélgetés törlése + + + + Remove contact + Kapcsolat eltávolítása + + + + Block contact + Kapcsolat letiltása + + + + Copy number + Szám másolása + + + + Search your received invitations + Megérkezett meghívások keresése + + + + Contact me on Jami + Lépjen kapcsolatba velem a Jami-n + + + + My Id is : + Az azonosítóm: + + + + %1 + %1 is the contact username + %1 + + + + %1 + %1 is the contact unique identifier + %1 + + + + Call incoming from %1 + Bejövő hívás tőle: %1 + + + + DeleteAccountDialog + + + Account deletion + Fiók eltávolítása + + + + Do you really want to delete the following account? + Tényleg törli ezt az fiókot? + + + + If this account hasn't been exported, or added to another device, it will be irrevocably lost. + Ha ezt a fiókot nem exportálták vagy hozzáadták egy másik eszközhöz, akkor ez el fog veszni. + + + + Permanently delete account + Fiók végleges törlése + + + + Delete + Törlés + + + + Cancel account deletion + Fiók eltávolítás megszakítása + + + + Cancel + Mé_gse + + + + DeviceItemWidget + + + Form + Feladó + + + + Device Id + Eszközazonosító + + + + this device + ez az eszköz + + + + InviteButtonsWidget + + + Accept + Elfogadás + + + + Refuse + Elutasítás + + + + Block + Letiltás + + + + LinkDeviceDialog + + + Dialog + Párbeszédpanel + + + + Enter your account password + Adja meg fiókjának jelszavát + + + + Password + Jelszó + + + + Ok + Rendben + + + + Cancel + Mégse + + + + Exporting account + Fiók exportálása + + + + Your PIN is + A PIN-kódja + + + + PIN + PIN-kód + + + + This pin and the account password should be entered in your device within 10 minutes. + Ezt a PIN-kódot és a fiók jelszót 10 percen belül be kell írni a eszközbe. + + + + Close + Bezárás + + + + Link Another Device + Csatlakoztasson másik eszközt + + + + Incorrect password + Hibás jelszó + + + + Something went wrong. +Please try again later. + Valami hiba történt. +Próbálja meg újra később. + + + + MainWindow + + + Settings + Beállítások + + + + Exit + Kilépés + + + + About + Névjegy + + + + Jami + Jami + + + + NameRegistrationDialog + + + Set Registered Name + Bejegyzett név beállítása + + + + Enter your account password + Adja meg fiókjának jelszavát + + + + Password text input + Jelszó szövegbevitel + + + + Password text entry + Jelszó beírása + + + + Password + Jelszó + + + + Register + Bejegyez + + + + Cancel + Mégse + + + + Registering Name + Név bejegyzése + + + + Something went wrong + Valami hiba történt + + + + Close + Bezárás + + + + Incorrect password + Hibás jelszó + + + + Network error + Hálózati hiba + + + + NewWizardWidget + + + Form + Feladó + + + + Welcome Label + Üdvözlő címke + + + + Welcome to + Isten hozott + + + + Welcome Logo + Üdvözlő jelkép + + + + Create Jami account button + Jami fiók létrehozása gomb + + + + Push button for Jami account creation start trigger + Nyomógomb a Jami fiók létrehozás indításának aktivizálásához + + + + Create a Jami account + Jami-fiók létrehozása + + + + Link device button + Összekapcsoló eszköz gombja + + + + Push button for device linkage start trigger + Nyomógomb a készülék összekapcsolásának indítási triggerjére + + + + Link this device to an account + Ezen eszköz összekapcsolása egy fiókhoz + + + + Create Jami SIP account button + Jami SIP-fiók létrehozása gomb + + + + Push button for Jami SIP account creation start trigger + Nyomógomb a Jami-/SIP-fiók létrehozás indításának aktivizálásához + + + + Create a SIP account + SIP fiók létrehozása + + + + Link this device to an existing account + Ezen eszköz egy létező fiókhoz kapcsolása + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Ubuntu'; font-size:14px; color:#555555;">To link this device to another account, you first </span><span style=" font-family:'Ubuntu'; font-size:14px; font-weight:600; color:#555555;">need to obtain a PIN</span><span style=" font-family:'Ubuntu'; font-size:14px; color:#555555;"> code. To generate the PIN code:</span></p> +<ol style="margin-top: 0px; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; -qt-list-indent: 1;"><li style=" font-family:'Ubuntu'; font-size:14px; color:#555555;" style=" margin-top:12px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:14px;">Go to the </span><span style=" font-size:14px; font-weight:600;">Account management setting</span><span style=" font-size:14px;"> of a previous device</span></li> +<li style=" font-family:'Ubuntu'; font-size:14px; color:#555555;" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:14px;">Choose the </span><span style=" font-size:14px; font-weight:600;">Jami account</span><span style=" font-size:14px;"> you want to use</span></li> +<li style=" font-family:'Ubuntu'; font-size:14px; color:#555555;" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:14px;">Go to the </span><span style=" font-size:14px; font-weight:600;">Devices</span><span style=" font-size:14px;"> tab</span></li> +<li style=" font-family:'Ubuntu'; font-size:14px; color:#555555;" style=" margin-top:0px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:14px;">Select </span><span style=" font-size:14px; font-weight:600;">Add a device</span></li></ol> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Ubuntu'; font-size:14px; color:#555555;">You will get the necessary PIN to complete this form. The PIN is only valid for </span><span style=" font-family:'Ubuntu'; font-size:14px; font-weight:600; color:#555555;">10 minutes</span><span style=" font-family:'Ubuntu'; font-size:10px; color:#555555;">.</span></p></body></html> + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Ubuntu'; font-size:14px; color:#555555;">Először az eszköz összekapcsolása egy másik fiókkal </span><span style=" font-family:'Ubuntu'; font-size:14px; font-weight:600; color:#555555;">meg kell szereznie a PIN</span><span style=" font-family:'Ubuntu'; font-size:14px; color:#555555;">-kódot. A PIN kód létrehozása:</span></p> +<ol style="margin-top: 0px; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; -qt-list-indent: 1;"><li style=" font-family:'Ubuntu'; font-size:14px; color:#555555;" style=" margin-top:12px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:14px;">Menjen a </span><span style=" font-size:14px; font-weight:600;">Fiókkezelés beállítása</span><span style=" font-size:14px;"> egy korábbi eszközről</span></li> +<li style=" font-family:'Ubuntu'; font-size:14px; color:#555555;" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:14px;">Válassza a </span><span style=" font-size:14px; font-weight:600;">Jami fiók</span><span style=" font-size:14px;"> szeretné használni</span></li> +<li style=" font-family:'Ubuntu'; font-size:14px; color:#555555;" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:14px;">Menjen a </span><span style=" font-size:14px; font-weight:600;">Eszközök</span><span style=" font-size:14px;"> lap</span></li> +<li style=" font-family:'Ubuntu'; font-size:14px; color:#555555;" style=" margin-top:0px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:14px;">Válassza </span><span style=" font-size:14px; font-weight:600;">Eszköz hozzáadása</span></li></ol> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Ubuntu'; font-size:14px; color:#555555;">Kapja meg a szükséges PIN-kódot az űrlap kitöltéséhez. A PIN-kód csak érvényes </span><span style=" font-family:'Ubuntu'; font-size:14px; font-weight:600; color:#555555;">10 percig</span><span style=" font-family:'Ubuntu'; font-size:10px; color:#555555;">.</span></p></body></html> + + + + Enter your pin: + Adja meg a PIN-kódját: + + + + Or import a file: + Vagy egy fájl importálása: + + + + Link from exported account archive file + Exportált fiók összekapcsolása archív fájlból + + + + + + (None) + (Nincs) + + + + Password: + Jelszó: + + + + + Profile + Profil + + + + + Profile name + Profilnév + + + + Account + Fiók + + + + Register your username. +This will reserve the username so that only you can use it. +Your friends will be able to call you with your usename +instead of using your ID. + Bejegyeztetés a felhasználónevét. +Ez fenntartja a felhasználónevet, hogy csak Ön tudja használni. +Ismerősei képesek lesznek felhívni a felhasználónevét az azonosító használata helyett. + + + + Public username checkbox + Nyilvános felhasználónév jelölőnégyzet + + + + Checkbox selecting if the user wants a public username + Válassza ki a jelölőnégyzetet, ha a felhasználó nyilvános felhasználónevet szeretne + + + + Register public username + Nyilvános felhasználónév bejegyeztetése + + + + Public username edit + Nyilvános felhasználónév szerkesztés + + + + Choose your username + Válasszon egy felhasználónevet + + + + Password text input + Jelszó szövegbevitel + + + + Password text entry + Jelszó beírása + + + + + Password + Jelszó + + + + + Password confirmation text input + Jelszó megerősítési szövegbevitel + + + + Confirm password + Jelszó megerősítése + + + + SIP Account + SIP fiók + + + + SIP Server edit + SIP-kiszolgáló szerkesztése + + + + Server + Kiszolgáló + + + + SIP proxy input + SIP-meghatalmazott bevitel + + + + SIP proxy text entry + SIP-meghatalmazott szövegbevitel + + + + Proxy + Meghatalmazott + + + + SIP username input + SIP felhasználónév bevitel + + + + SIP Password text entry + SIP jelszó szövegbevitel + + + + Username + Felhasználónév + + + + + SIP Password text input + SIP jelszó szöveg bemenet + + + + Generating your Jami account… + Jami fiók létrehozása… + + + + Previous page button + Előző oldal gombja + + + + push button to access previous page of wizard + nyomógomb az előző oldal hozzáférésének varázslója + + + + Previous + Vissza + + + + Cancel account create/link + Fiók létrehozása-/összekapcsolása megszakítása + + + + push button to cancel account creation or linking + nyomja meg a gombot a fiók létrehozása-/összekapcsolása megszakításához + + + + Back + Vissza + + + + Next page Button + Következő oldal gombja + + + + Push button to access next page of wizard + Nyomógomb a következő oldal hozzáférésének varázslója + + + + Next + Tovább + + + + Open File + Fájl megnyitása + + + + Jami archive files (*.gz); All files (*) + Jami archív fájlok (*.gz); Minden fájl (*) + + + + Your account needs to be migrated. Enter your password. + Fiók áttelepítés szükséges. Adja meg a jelszavát. + + + + Migrating your Jami account... + Jami-fiók áttelepítése… + + + + Importing account archive... + Fiók archívum importálása… + + + + Generating your Jami account... + Jami-fiók létrehozása… + + + + Generating your SIP account... + A SIP-fiók létrehozása… + + + + Error creating account + Hiba a fiók létrehozása során + + + + PasswordDialog + + + Change Account Password + Fiók jelszóváltoztatása + + + + Enter Current Password + Adja meg a jelenlegi jelszót + + + + Enter New Password + Új jelszó megadása + + + + Confirm New Password + Új jelszó megerősítése + + + + Confirm + Megerősítés + + + + Cancel + Mégse + + + + Current Password Incorrect + Hibás jelenlegi jelszót + + + + PhotoBoothDialog + + + Photobooth + Fénykép automata + + + + PhotoboothWidget + + + Form + Feladó + + + + Photobooth display + Fénykép automata kijelző + + + + Choose File + Fájl kiválasztása + + + + Image Files (*.jpg *.jpeg *.png) + Képfájlok (*.jpeg *.jpg *.png) + + + + PrivateBridging + + + Choose File + Fájl kiválasztása + + + + Files (*) + Fájlok (*) + + + + QObject + + + No default mail client found + Nem találtam alapértelmezett levelezőügyfélt + + + + + Edit Device Name + Eszköznév szerkesztése + + + + Unlink Device From Account + Ezen eszköz fiókhoz kikapcsolása + + + + Save new device name + Új eszköz nevének mentése + + + + Add as contact + Hozzáadás a partnerekhez + + + + RingButton + + + Select folder + Mappa kijelölése + + + + SettingsWidget + + + Form + Feladó + + + + Settings + Beállítások + + + + Account + Fiók + + + + + General + Általános + + + + + Audio / Video + Hang/Videó + + + + System + Rendszer + + + + Enable desktop notifications + Az asztali értesítések engedélyezése + + + + Keep minimized on close + Bezáráskor legyen minimalizálva + + + + Download folder + Letöltés mappa + + + + Save in + Mentés helye + + + + Always Recording + Mindig legyen felvétel + + + + Updates + Frissítések + + + + Check for updates automatically every + Frissítések keresése minden + + + + Interval between update checks in days selector + Időközönkénti frissítések ellenőrzése napi választó + + + + days + nap + + + + Check for updates now button + Frissítések ellenőrzése most gomb + + + + Check for updates now + Frissítések ellenőrzése most + + + + Password + Jelszó + + + + + Enable + Engedélyezés + + + + toggle enable notifications + Értesítések engedélyezése be-/kikapcsolása + + + + Toggle keep minimized on close + Bezáráskor minimalizálás be-/kikapcsolása + + + + Call Recordings + Hívás felvételek + + + + Toggle automatic updates + Önműködő frissítések engedélyezése be-/kikapcsolása + + + + Jami Account + Jami fiók + + + + + Profile + Profil + + + + + Identity + Személyazonosság + + + + Id + Azonosító + + + + Registered name + Bejegyzett név + + + + Type here to register a username + Adja meg a felhasználónév bejegyeztetése ide + + + + Register + Bejegyez + + + + Change Password + Jelszó megváltoztatása + + + + Export Account + Fiók exportálása + + + + + Delete Account + Fiók törlése + + + + Linked Devices + Összekapcsolt eszközök + + + + Link Another Device + Csatlakoztasson másik eszközt + + + + Banned Contacts + Letiltott kapcsolatok + + + + Format + Formátum + + + + Video device framerate selector + Videó eszköz képkocka sebességválasztó + + + + Preview unavailable + Előnézet nem érhető el + + + + + Advanced Account Settings + Haladó fiókbeállítások + + + + SIP Account + SIP fiók + + + + Username + Felhasználónév + + + + Hostname + Kiszolgálónév + + + + Proxy + Meghatalmazott + + + + Audio + Hang + + + + Microphone + Mikrofon + + + + Audio input device selector + Audió bemeneti eszköz választó + + + + Output Device + Kimeneti eszköz + + + + Choose the output device + Válasszon ki egy kimeneti eszközt + + + + Video + Videó + + + + Device + Eszköz + + + + Video device selector + Videó eszköz választó + + + + A registered name should not have any spaces and must be at least three letters long + A bejegyzett névnek nem szabad szóközt lennie, és legalább három betűnek kell lennie + + + + This name is already taken + A név már foglalt + + + + + Enter an alias + Adjon meg egy álnevet + + + + Register this name + Bejegyeztetés ezt a nevet + + + + Remove Device + Eszköz eltávolítása + + + + Enter this account's password to confirm the removal of this device + Adja meg a fiók jelszót ehhez eszköz eltávolításának megerősítéséhez + + + + Are you sure you wish to remove this device? + Biztosan eltávolítja ezt az eszközt? + + + + Export Account Here + Fiók exportálása ide + + + + Select A Folder For Your Downloads + Letöltés célmappájának választása + + + + Select A Folder For Your Recordings + Felvétel célmappájának választása + + + + VideoOverlay + + + Call on Hold + Hívástartás + + + + Hold / Unhold + Tartás/Tartás megszüntetése + + + + Chat + Csevegés + + + + Mute Mic + Mikrofon elnémítása + + + + Record call + Hívás felvétele + + + + Name label + Névcímke + + + + Time elapsed + Eltelt idő + + + + 00:00 + 00:00 + + + + Hangup + Hívás befejezése + + + + Mute Video + Videó némítása + + + + VideoView + + + Share entire screen + Az egész képernyő megosztása + + + + Share screen area + Képernyő részének megosztása + + + + Share file + Fájl megosztása + + + \ No newline at end of file diff --git a/translations/ring_client_windows_id.ts b/translations/ring_client_windows_id.ts new file mode 100644 index 00000000..ef7932f0 --- /dev/null +++ b/translations/ring_client_windows_id.ts @@ -0,0 +1,1589 @@ + + + AboutDialog + + + + About + + + + + about button + + + + + credits button + + + + + Credits + Partisipan + + + + Free as in Freedom + + + + + The Microsoft Windows client for Jami. +Jami is a secured and distributed communication software. + + + + + version + + + + + Created by: + + + + + Artwork by: + + + + + Based on the SFLPhone project + + + + + AccountItemDelegate + + + Add Account + + + + + AdvancedSIPSettingsWidget + + + Form + + + + + Call Settings + + + + + Auto Answer Calls + + + + + Enable Custom Ringtone + + + + + Connectivity + + + + + STUN Address + + + + + Use STUN + + + + + Use UPnP + + + + + Use TURN + + + + + TURN Password + + + + + TURN Username + + + + + TURN Address + + + + + Media + + + + + Enable Video + + + + + Video Codecs + + + + + Audio Codecs + + + + + Audio Files (*.wav *.ogg *.opus *.mp3 *aiff *wma) + + + + + Add a custom ringtone + + + + + AdvancedSettingsWidget + + + Form + + + + + Call Settings + + + + + Allow Calls From Untrusted Peers + + + + + Auto Answer Calls + + + + + Enable Custom Ringtone + + + + + Add a custom ringtone + + + + + Name Server + + + + + Address + + + + + OpenDHT Configuration + + + + + Enable Proxy + + + + + Bootstrap + + + + + Security + + + + + Private Key Password + + + + + User Certificate + + + + + Private Key + + + + + CA Certificate + + + + + Connectivity + + + + + Use STUN + + + + + STUN Address + + + + + Use UPnP + + + + + Use TURN + + + + + TURN Password + + + + + TURN Username + + + + + TURN Address + + + + + Media + + + + + Enable Video + + + + + Audio Codecs + + + + + Video Codecs + + + + + Audio Files (*.wav *.ogg *.opus *.mp3 *aiff *wma) + + + + + AnimatedOverlay + + + Form + + + + + BannedItemWidget + + + Form + + + + + name + + + + + id + + + + + CallWidget + + + Show conversations + + + + + Conversations + + + + + Search contact text input + + + + + Jami is free software for universal communication which respects the freedoms and privacy of its users. + Jami adalah perangkat lunak gratis untuk komunikasi universal yang menghormati kebebasan dan privasi penggunanya + + + + + This is your ID. +Copy and share it with your friends! + + + + + + Show ring ID QR code + + + + + Share ring ID button + + + + + Double-click to copy + + + + + Error while generating QR Code + + + + + + best name + + + + + best Id + + + + + Back to homepage button + + + + + Add to contacts + Tambah sebagai kontak + + + + Show invites + + + + + Invites + + + + + + Find a new or existing contact + + + + + Wants to talk to you! + + + + + Answer incoming call button + + + + + Ignore incoming call button + + + + + Answer + + + + + Ignore + + + + + Cancel outgoing call + + + + + Cancel + + + + + Start video call + + + + + Start audio call + + + + + Clear conversation + + + + + Remove contact + + + + + Block contact + + + + + Copy number + Salin nomor + + + + Search your received invitations + + + + + Contact me on Jami + + + + + My Id is : + + + + + %1 + %1 is the contact username + + + + + %1 + %1 is the contact unique identifier + + + + + Call incoming from %1 + + + + + DeleteAccountDialog + + + Account deletion + + + + + Do you really want to delete the following account? + + + + + If this account hasn't been exported, or added to another device, it will be irrevocably lost. + + + + + Permanently delete account + + + + + Delete + + + + + Cancel account deletion + + + + + Cancel + + + + + DeviceItemWidget + + + Form + + + + + Device Id + + + + + this device + + + + + InviteButtonsWidget + + + Accept + Terima + + + + Refuse + Tolak + + + + Block + Blokir + + + + LinkDeviceDialog + + + Dialog + + + + + Enter your account password + + + + + Password + + + + + Ok + + + + + Cancel + + + + + Exporting account + + + + + Your PIN is + + + + + PIN + + + + + This pin and the account password should be entered in your device within 10 minutes. + + + + + Close + + + + + Link Another Device + + + + + Incorrect password + + + + + Something went wrong. +Please try again later. + + + + + MainWindow + + + Settings + Setelan + + + + Exit + + + + + About + + + + + Jami + + + + + NameRegistrationDialog + + + Set Registered Name + + + + + Enter your account password + + + + + Password text input + + + + + Password text entry + + + + + Password + + + + + Register + + + + + Cancel + + + + + Registering Name + + + + + Something went wrong + + + + + Close + + + + + Incorrect password + + + + + Network error + + + + + NewWizardWidget + + + Form + + + + + Welcome Label + + + + + Welcome to + + + + + Welcome Logo + + + + + Create Jami account button + + + + + Push button for Jami account creation start trigger + + + + + Create a Jami account + + + + + Link device button + + + + + Push button for device linkage start trigger + + + + + Link this device to an account + + + + + Create Jami SIP account button + + + + + Push button for Jami SIP account creation start trigger + + + + + Create a SIP account + + + + + Link this device to an existing account + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Ubuntu'; font-size:14px; color:#555555;">To link this device to another account, you first </span><span style=" font-family:'Ubuntu'; font-size:14px; font-weight:600; color:#555555;">need to obtain a PIN</span><span style=" font-family:'Ubuntu'; font-size:14px; color:#555555;"> code. To generate the PIN code:</span></p> +<ol style="margin-top: 0px; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; -qt-list-indent: 1;"><li style=" font-family:'Ubuntu'; font-size:14px; color:#555555;" style=" margin-top:12px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:14px;">Go to the </span><span style=" font-size:14px; font-weight:600;">Account management setting</span><span style=" font-size:14px;"> of a previous device</span></li> +<li style=" font-family:'Ubuntu'; font-size:14px; color:#555555;" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:14px;">Choose the </span><span style=" font-size:14px; font-weight:600;">Jami account</span><span style=" font-size:14px;"> you want to use</span></li> +<li style=" font-family:'Ubuntu'; font-size:14px; color:#555555;" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:14px;">Go to the </span><span style=" font-size:14px; font-weight:600;">Devices</span><span style=" font-size:14px;"> tab</span></li> +<li style=" font-family:'Ubuntu'; font-size:14px; color:#555555;" style=" margin-top:0px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:14px;">Select </span><span style=" font-size:14px; font-weight:600;">Add a device</span></li></ol> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Ubuntu'; font-size:14px; color:#555555;">You will get the necessary PIN to complete this form. The PIN is only valid for </span><span style=" font-family:'Ubuntu'; font-size:14px; font-weight:600; color:#555555;">10 minutes</span><span style=" font-family:'Ubuntu'; font-size:10px; color:#555555;">.</span></p></body></html> + + + + + Enter your pin: + + + + + Or import a file: + + + + + Link from exported account archive file + + + + + + + (None) + + + + + Password: + + + + + + Profile + Profil + + + + + Profile name + + + + + Account + Akun + + + + Register your username. +This will reserve the username so that only you can use it. +Your friends will be able to call you with your usename +instead of using your ID. + + + + + Public username checkbox + + + + + Checkbox selecting if the user wants a public username + + + + + Register public username + + + + + Public username edit + + + + + Choose your username + + + + + Password text input + + + + + Password text entry + + + + + + Password + + + + + + Password confirmation text input + + + + + Confirm password + + + + + SIP Account + + + + + SIP Server edit + + + + + Server + + + + + SIP proxy input + + + + + SIP proxy text entry + + + + + Proxy + + + + + SIP username input + + + + + SIP Password text entry + + + + + Username + + + + + + SIP Password text input + + + + + Generating your Jami account… + + + + + Previous page button + + + + + push button to access previous page of wizard + + + + + Previous + + + + + Cancel account create/link + + + + + push button to cancel account creation or linking + + + + + Back + Kembali + + + + Next page Button + + + + + Push button to access next page of wizard + + + + + Next + Selanjutnya + + + + Open File + + + + + Jami archive files (*.gz); All files (*) + + + + + Your account needs to be migrated. Enter your password. + + + + + Migrating your Jami account... + + + + + Importing account archive... + + + + + Generating your Jami account... + + + + + Generating your SIP account... + + + + + Error creating account + + + + + PasswordDialog + + + Change Account Password + + + + + Enter Current Password + + + + + Enter New Password + + + + + Confirm New Password + + + + + Confirm + + + + + Cancel + + + + + Current Password Incorrect + + + + + PhotoBoothDialog + + + Photobooth + + + + + PhotoboothWidget + + + Form + + + + + Photobooth display + + + + + Choose File + + + + + Image Files (*.jpg *.jpeg *.png) + + + + + PrivateBridging + + + Choose File + + + + + Files (*) + + + + + QObject + + + No default mail client found + + + + + + Edit Device Name + + + + + Unlink Device From Account + + + + + Save new device name + + + + + Add as contact + + + + + RingButton + + + Select folder + + + + + SettingsWidget + + + Form + + + + + Settings + Setelan + + + + Account + Akun + + + + + General + + + + + + Audio / Video + + + + + System + + + + + Enable desktop notifications + + + + + Keep minimized on close + + + + + Download folder + + + + + Save in + + + + + Always Recording + + + + + Updates + + + + + Check for updates automatically every + + + + + Interval between update checks in days selector + + + + + days + + + + + Check for updates now button + + + + + Check for updates now + + + + + Password + + + + + + Enable + + + + + toggle enable notifications + + + + + Toggle keep minimized on close + + + + + Call Recordings + + + + + Toggle automatic updates + + + + + Jami Account + + + + + + Profile + Profil + + + + + Identity + + + + + Id + + + + + Registered name + + + + + Type here to register a username + + + + + Register + + + + + Change Password + + + + + Export Account + + + + + + Delete Account + + + + + Linked Devices + + + + + Link Another Device + + + + + Banned Contacts + + + + + Format + + + + + Video device framerate selector + + + + + Preview unavailable + + + + + + Advanced Account Settings + + + + + SIP Account + + + + + Username + + + + + Hostname + + + + + Proxy + + + + + Audio + Suara + + + + Microphone + + + + + Audio input device selector + + + + + Output Device + + + + + Choose the output device + + + + + Video + Video + + + + Device + + + + + Video device selector + + + + + A registered name should not have any spaces and must be at least three letters long + + + + + This name is already taken + + + + + + Enter an alias + + + + + Register this name + + + + + Remove Device + + + + + Enter this account's password to confirm the removal of this device + + + + + Are you sure you wish to remove this device? + + + + + Export Account Here + + + + + Select A Folder For Your Downloads + + + + + Select A Folder For Your Recordings + + + + + VideoOverlay + + + Call on Hold + + + + + Hold / Unhold + + + + + Chat + + + + + Mute Mic + + + + + Record call + + + + + Name label + + + + + Time elapsed + + + + + 00:00 + + + + + Hangup + + + + + Mute Video + + + + + VideoView + + + Share entire screen + + + + + Share screen area + + + + + Share file + + + + \ No newline at end of file diff --git a/translations/ring_client_windows_it.ts b/translations/ring_client_windows_it.ts new file mode 100644 index 00000000..493adcc8 --- /dev/null +++ b/translations/ring_client_windows_it.ts @@ -0,0 +1,1589 @@ + + + AboutDialog + + + + About + + + + + about button + + + + + credits button + + + + + Credits + Crediti + + + + Free as in Freedom + + + + + The Microsoft Windows client for Jami. +Jami is a secured and distributed communication software. + + + + + version + versione + + + + Created by: + + + + + Artwork by: + + + + + Based on the SFLPhone project + + + + + AccountItemDelegate + + + Add Account + Aggiungi Account + + + + AdvancedSIPSettingsWidget + + + Form + + + + + Call Settings + + + + + Auto Answer Calls + + + + + Enable Custom Ringtone + + + + + Connectivity + Connettività + + + + STUN Address + + + + + Use STUN + Usare STUN + + + + Use UPnP + + + + + Use TURN + Usare TURN + + + + TURN Password + + + + + TURN Username + + + + + TURN Address + + + + + Media + Media + + + + Enable Video + Attivare Video + + + + Video Codecs + + + + + Audio Codecs + + + + + Audio Files (*.wav *.ogg *.opus *.mp3 *aiff *wma) + + + + + Add a custom ringtone + + + + + AdvancedSettingsWidget + + + Form + + + + + Call Settings + + + + + Allow Calls From Untrusted Peers + Consenti chiamate da peer non attendibili + + + + Auto Answer Calls + + + + + Enable Custom Ringtone + + + + + Add a custom ringtone + + + + + Name Server + + + + + Address + Indirizzo + + + + OpenDHT Configuration + + + + + Enable Proxy + + + + + Bootstrap + Innesco + + + + Security + Sicurezza + + + + Private Key Password + Password della chiave privata + + + + User Certificate + + + + + Private Key + + + + + CA Certificate + + + + + Connectivity + Connettività + + + + Use STUN + Usare STUN + + + + STUN Address + + + + + Use UPnP + + + + + Use TURN + Usare TURN + + + + TURN Password + + + + + TURN Username + + + + + TURN Address + + + + + Media + Media + + + + Enable Video + Attivare Video + + + + Audio Codecs + + + + + Video Codecs + + + + + Audio Files (*.wav *.ogg *.opus *.mp3 *aiff *wma) + + + + + AnimatedOverlay + + + Form + + + + + BannedItemWidget + + + Form + + + + + name + + + + + id + + + + + CallWidget + + + Show conversations + + + + + Conversations + Converzazioni + + + + Search contact text input + + + + + Jami is free software for universal communication which respects the freedoms and privacy of its users. + Jami è un software gratuito per la comunicazione universale che rispetta le libertà e la privacy dei suoi utenti. + + + + + This is your ID. +Copy and share it with your friends! + + + + + + Show ring ID QR code + + + + + Share ring ID button + + + + + Double-click to copy + + + + + Error while generating QR Code + + + + + + best name + + + + + best Id + + + + + Back to homepage button + + + + + Add to contacts + Aggiungi contatti + + + + Show invites + + + + + Invites + + + + + + Find a new or existing contact + + + + + Wants to talk to you! + + + + + Answer incoming call button + + + + + Ignore incoming call button + + + + + Answer + Rispondi + + + + Ignore + Ignora + + + + Cancel outgoing call + + + + + Cancel + Cancella + + + + Start video call + + + + + Start audio call + + + + + Clear conversation + + + + + Remove contact + Rimuovi contatto + + + + Block contact + Blocca contatto + + + + Copy number + Copia il numerp + + + + Search your received invitations + + + + + Contact me on Jami + + + + + My Id is : + + + + + %1 + %1 is the contact username + %1 + + + + %1 + %1 is the contact unique identifier + %1 + + + + Call incoming from %1 + + + + + DeleteAccountDialog + + + Account deletion + + + + + Do you really want to delete the following account? + + + + + If this account hasn't been exported, or added to another device, it will be irrevocably lost. + + + + + Permanently delete account + + + + + Delete + Cancella + + + + Cancel account deletion + + + + + Cancel + Cancella + + + + DeviceItemWidget + + + Form + + + + + Device Id + + + + + this device + questo dispositivo + + + + InviteButtonsWidget + + + Accept + Accettare + + + + Refuse + Rifiuta + + + + Block + Blocca + + + + LinkDeviceDialog + + + Dialog + + + + + Enter your account password + + + + + Password + Password + + + + Ok + Ok + + + + Cancel + Cancella + + + + Exporting account + Esportazione account in corso + + + + Your PIN is + Il tuo PIN è + + + + PIN + PIN + + + + This pin and the account password should be entered in your device within 10 minutes. + + + + + Close + Chiudi + + + + Link Another Device + + + + + Incorrect password + + + + + Something went wrong. +Please try again later. + + + + + MainWindow + + + Settings + Impostazioni + + + + Exit + + + + + About + + + + + Jami + Jami + + + + NameRegistrationDialog + + + Set Registered Name + + + + + Enter your account password + + + + + Password text input + + + + + Password text entry + + + + + Password + Password + + + + Register + Register + + + + Cancel + Cancella + + + + Registering Name + + + + + Something went wrong + + + + + Close + Chiudi + + + + Incorrect password + + + + + Network error + Errore di rete + + + + NewWizardWidget + + + Form + + + + + Welcome Label + + + + + Welcome to + Benvenuto in + + + + Welcome Logo + + + + + Create Jami account button + + + + + Push button for Jami account creation start trigger + + + + + Create a Jami account + Crea un account Jami + + + + Link device button + + + + + Push button for device linkage start trigger + + + + + Link this device to an account + Collega questo dispositivo a un account + + + + Create Jami SIP account button + + + + + Push button for Jami SIP account creation start trigger + + + + + Create a SIP account + + + + + Link this device to an existing account + Collega questo dispositivo a un account esistente + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Ubuntu'; font-size:14px; color:#555555;">To link this device to another account, you first </span><span style=" font-family:'Ubuntu'; font-size:14px; font-weight:600; color:#555555;">need to obtain a PIN</span><span style=" font-family:'Ubuntu'; font-size:14px; color:#555555;"> code. To generate the PIN code:</span></p> +<ol style="margin-top: 0px; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; -qt-list-indent: 1;"><li style=" font-family:'Ubuntu'; font-size:14px; color:#555555;" style=" margin-top:12px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:14px;">Go to the </span><span style=" font-size:14px; font-weight:600;">Account management setting</span><span style=" font-size:14px;"> of a previous device</span></li> +<li style=" font-family:'Ubuntu'; font-size:14px; color:#555555;" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:14px;">Choose the </span><span style=" font-size:14px; font-weight:600;">Jami account</span><span style=" font-size:14px;"> you want to use</span></li> +<li style=" font-family:'Ubuntu'; font-size:14px; color:#555555;" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:14px;">Go to the </span><span style=" font-size:14px; font-weight:600;">Devices</span><span style=" font-size:14px;"> tab</span></li> +<li style=" font-family:'Ubuntu'; font-size:14px; color:#555555;" style=" margin-top:0px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:14px;">Select </span><span style=" font-size:14px; font-weight:600;">Add a device</span></li></ol> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Ubuntu'; font-size:14px; color:#555555;">You will get the necessary PIN to complete this form. The PIN is only valid for </span><span style=" font-family:'Ubuntu'; font-size:14px; font-weight:600; color:#555555;">10 minutes</span><span style=" font-family:'Ubuntu'; font-size:10px; color:#555555;">.</span></p></body></html> + + + + + Enter your pin: + Inserisci il tuo pin: + + + + Or import a file: + O importa un file: + + + + Link from exported account archive file + + + + + + + (None) + (Nessuno) + + + + Password: + Password: + + + + + Profile + Profilo + + + + + Profile name + + + + + Account + Profilo + + + + Register your username. +This will reserve the username so that only you can use it. +Your friends will be able to call you with your usename +instead of using your ID. + + + + + Public username checkbox + + + + + Checkbox selecting if the user wants a public username + + + + + Register public username + + + + + Public username edit + + + + + Choose your username + + + + + Password text input + + + + + Password text entry + + + + + + Password + Password + + + + + Password confirmation text input + + + + + Confirm password + Confermare password + + + + SIP Account + Account SIP + + + + SIP Server edit + + + + + Server + + + + + SIP proxy input + + + + + SIP proxy text entry + + + + + Proxy + Proxy + + + + SIP username input + + + + + SIP Password text entry + + + + + Username + Nome utente + + + + + SIP Password text input + + + + + Generating your Jami account… + Generare il tuo account Jami ... + + + + Previous page button + + + + + push button to access previous page of wizard + + + + + Previous + Precedente + + + + Cancel account create/link + + + + + push button to cancel account creation or linking + + + + + Back + Indietro + + + + Next page Button + + + + + Push button to access next page of wizard + + + + + Next + Seguente + + + + Open File + + + + + Jami archive files (*.gz); All files (*) + + + + + Your account needs to be migrated. Enter your password. + + + + + Migrating your Jami account... + + + + + Importing account archive... + + + + + Generating your Jami account... + + + + + Generating your SIP account... + + + + + Error creating account + + + + + PasswordDialog + + + Change Account Password + + + + + Enter Current Password + + + + + Enter New Password + + + + + Confirm New Password + + + + + Confirm + + + + + Cancel + Cancella + + + + Current Password Incorrect + + + + + PhotoBoothDialog + + + Photobooth + + + + + PhotoboothWidget + + + Form + + + + + Photobooth display + + + + + Choose File + + + + + Image Files (*.jpg *.jpeg *.png) + + + + + PrivateBridging + + + Choose File + + + + + Files (*) + + + + + QObject + + + No default mail client found + + + + + + Edit Device Name + + + + + Unlink Device From Account + + + + + Save new device name + + + + + Add as contact + + + + + RingButton + + + Select folder + + + + + SettingsWidget + + + Form + + + + + Settings + Impostazioni + + + + Account + Profilo + + + + + General + Generale + + + + + Audio / Video + + + + + System + Sistema + + + + Enable desktop notifications + + + + + Keep minimized on close + + + + + Download folder + Cartella download + + + + Save in + + + + + Always Recording + + + + + Updates + + + + + Check for updates automatically every + + + + + Interval between update checks in days selector + + + + + days + giorni + + + + Check for updates now button + + + + + Check for updates now + + + + + Password + Password + + + + + Enable + + + + + toggle enable notifications + + + + + Toggle keep minimized on close + + + + + Call Recordings + + + + + Toggle automatic updates + + + + + Jami Account + Account Jami + + + + + Profile + Profilo + + + + + Identity + Identità + + + + Id + + + + + Registered name + + + + + Type here to register a username + + + + + Register + Register + + + + Change Password + + + + + Export Account + + + + + + Delete Account + + + + + Linked Devices + + + + + Link Another Device + + + + + Banned Contacts + + + + + Format + + + + + Video device framerate selector + + + + + Preview unavailable + + + + + + Advanced Account Settings + + + + + SIP Account + Account SIP + + + + Username + Nome utente + + + + Hostname + Nome Host + + + + Proxy + Proxy + + + + Audio + Audio + + + + Microphone + + + + + Audio input device selector + + + + + Output Device + + + + + Choose the output device + + + + + Video + Video + + + + Device + Dispositivo + + + + Video device selector + + + + + A registered name should not have any spaces and must be at least three letters long + + + + + This name is already taken + + + + + + Enter an alias + + + + + Register this name + + + + + Remove Device + + + + + Enter this account's password to confirm the removal of this device + + + + + Are you sure you wish to remove this device? + + + + + Export Account Here + + + + + Select A Folder For Your Downloads + + + + + Select A Folder For Your Recordings + + + + + VideoOverlay + + + Call on Hold + + + + + Hold / Unhold + + + + + Chat + Chat + + + + Mute Mic + + + + + Record call + + + + + Name label + + + + + Time elapsed + + + + + 00:00 + + + + + Hangup + Riattacare + + + + Mute Video + + + + + VideoView + + + Share entire screen + + + + + Share screen area + Condividere una porzione dello schermo + + + + Share file + Condividere file + + + \ No newline at end of file diff --git a/translations/ring_client_windows_it_IT.ts b/translations/ring_client_windows_it_IT.ts new file mode 100644 index 00000000..e0b0dcd9 --- /dev/null +++ b/translations/ring_client_windows_it_IT.ts @@ -0,0 +1,1606 @@ + + + AboutDialog + + + + About + Informazioni su + + + + about button + pulsante informazioni su + + + + credits button + pulsante crediti + + + + Credits + Crediti + + + + Free as in Freedom + Free as in Freedom + + + + The Microsoft Windows client for Jami. +Jami is a secured and distributed communication software. + Il client Microsoft Windows per Jami. +Jami è un software di comunicazione sicuro e distribuito. + + + + version + versione + + + + Created by: + Creato da: + + + + Artwork by: + Tema di: + + + + Based on the SFLPhone project + Basato sul progetto SFLPhone + + + + AccountItemDelegate + + + Add Account + Aggiungi account + + + + AdvancedSIPSettingsWidget + + + Form + Modulo + + + + Call Settings + Impostazioni di chiamata + + + + Auto Answer Calls + Risposta automatica alle chiamate + + + + Enable Custom Ringtone + Abilita suoneria personalizzata + + + + Connectivity + Connettività + + + + STUN Address + Indirizzo STUN + + + + Use STUN + Utilizza STUN + + + + Use UPnP + Usa UPnP + + + + Use TURN + Utilizza TURN + + + + TURN Password + TURN Password + + + + TURN Username + TURN Nome Utente + + + + TURN Address + Indirizzo TURN + + + + Media + Media + + + + Enable Video + Attiva Video + + + + Video Codecs + Codec Video + + + + Audio Codecs + Codec audio + + + + Audio Files (*.wav *.ogg *.opus *.mp3 *aiff *wma) + File audio (* .wav * .ogg * .opus * .mp3 * aiff * wma) + + + + Add a custom ringtone + Aggiungi una suoneria personalizzata + + + + AdvancedSettingsWidget + + + Form + Modulo + + + + Call Settings + Impostazioni di chiamata + + + + Allow Calls From Untrusted Peers + Consenti chiamate da peer non attendibili + + + + Auto Answer Calls + Risposta automatica alle chiamate + + + + Enable Custom Ringtone + Abilita suoneria personalizzata + + + + Add a custom ringtone + Aggiungi una suoneria personalizzata + + + + Name Server + Nome Server + + + + Address + Indirizzo + + + + OpenDHT Configuration + Configurazione OpenDHT + + + + Enable Proxy + Abilita proxy + + + + Bootstrap + Avvio + + + + Security + Sicurezza + + + + Private Key Password + Password della Chiave Privata + + + + User Certificate + Certificato Utente + + + + Private Key + Chiave privata + + + + CA Certificate + Certificato CA. + + + + Connectivity + Connettività + + + + Use STUN + Utilizza STUN + + + + STUN Address + Indirizzo STUN + + + + Use UPnP + Usa UPnP + + + + Use TURN + Utilizza TURN + + + + TURN Password + TURN Password + + + + TURN Username + TURN Nome Utente + + + + TURN Address + Indirizzo TURN + + + + Media + Media + + + + Enable Video + Attiva Video + + + + Audio Codecs + Codec audio + + + + Video Codecs + Codec Video + + + + Audio Files (*.wav *.ogg *.opus *.mp3 *aiff *wma) + File audio (* .wav * .ogg * .opus * .mp3 * aiff * wma) + + + + AnimatedOverlay + + + Form + Modulo + + + + BannedItemWidget + + + Form + Modulo + + + + name + nome + + + + id + id + + + + CallWidget + + + Show conversations + Mostra conversazioni + + + + Conversations + Conversazioni + + + + Search contact text input + Cerca l'inserimento del testo del contatto + + + + Jami is free software for universal communication which respects the freedoms and privacy of its users. + Jami è un software gratuito per la comunicazione universale che rispetta le libertà e la privacy dei suoi utenti. + + + + + This is your ID. +Copy and share it with your friends! + + +Questo è il tuo ID. +Copia e condividi con i tuoi amici! + + + + + Show ring ID QR code + Mostra codice ID ring e QR code + + + + Share ring ID button + Condividi il pulsante ID ring + + + + Double-click to copy + Fare doppio clic per copiare + + + + Error while generating QR Code + Errore durante la generazione del Codice QR + + + + + best name + miglior nome + + + + best Id + miglior ID + + + + Back to homepage button + Torna al pulsante homepage + + + + Add to contacts + Aggiungi alla rubrica + + + + Show invites + Mostra inviti + + + + Invites + Inviti + + + + + Find a new or existing contact + Trova un contatto nuovo o esistente + + + + Wants to talk to you! + Vuole parlare con te! + + + + Answer incoming call button + Rispondi col pulsante di chiamata in arrivo + + + + Ignore incoming call button + Ignora il pulsante di chiamata in arrivo + + + + Answer + Rispondi + + + + Ignore + Ignora + + + + Cancel outgoing call + Annulla chiamata in uscita + + + + Cancel + Annulla + + + + Start video call + Inizia la video chiamata + + + + Start audio call + Avvia chiamata audio + + + + Clear conversation + Pulisci conversazione + + + + Remove contact + Rimuovi contatto + + + + Block contact + Blocca contatto + + + + Copy number + Copia numero + + + + Search your received invitations + Cerca i tuoi inviti ricevuti + + + + Contact me on Jami + Contattami su Jami + + + + My Id is : + Il mio ID è: + + + + %1 + %1 is the contact username + %1 + + + + %1 + %1 is the contact unique identifier + %1 + + + + Call incoming from %1 + Chiamata in arrivo da %1 + + + + DeleteAccountDialog + + + Account deletion + Cancellazione dell'account + + + + Do you really want to delete the following account? + Vuoi veramente cancellare il seguente account? + + + + If this account hasn't been exported, or added to another device, it will be irrevocably lost. + Se questo account non è stato esportato o aggiunto a un altro dispositivo, verrà perso in modo irrevocabile. + + + + Permanently delete account + Elimina definitivamente l'account + + + + Delete + Elimina + + + + Cancel account deletion + Annulla la cancellazione dell'account + + + + Cancel + Annulla + + + + DeviceItemWidget + + + Form + Modulo + + + + Device Id + ID del dispositivo + + + + this device + questo dispositivo + + + + InviteButtonsWidget + + + Accept + Accetta + + + + Refuse + Rifiuto + + + + Block + Blocca + + + + LinkDeviceDialog + + + Dialog + Dialog + + + + Enter your account password + Inserisci la password del tuo account + + + + Password + Password + + + + Ok + Ok + + + + Cancel + Annulla + + + + Exporting account + Esportazione dell'account + + + + Your PIN is + Il tuo PIN è + + + + PIN + PIN + + + + This pin and the account password should be entered in your device within 10 minutes. + Questo pin e la password dell'account devono essere inseriti nel dispositivo entro 10 minuti. + + + + Close + Chiudi + + + + Link Another Device + Collega un altro dispositivo + + + + Incorrect password + password errata + + + + Something went wrong. +Please try again later. + Qualcosa è andato storto. +Riprova più tardi. + + + + MainWindow + + + Settings + Opzioni + + + + Exit + Esci + + + + About + Info + + + + Jami + Jami + + + + NameRegistrationDialog + + + Set Registered Name + Imposta il nome registrato + + + + Enter your account password + Inserisci la password del tuo account + + + + Password text input + Inserimento testo password + + + + Password text entry + Inserimento testo password + + + + Password + Password + + + + Register + Salva + + + + Cancel + Annulla + + + + Registering Name + Nome di Registrazione + + + + Something went wrong + Qualcosa è andato storto + + + + Close + Chiudi + + + + Incorrect password + password errata + + + + Network error + Errore di rete + + + + NewWizardWidget + + + Form + Modulo + + + + Welcome Label + Etichetta di Benvenuto + + + + Welcome to + Benvenuto a + + + + Welcome Logo + Logo di benvenuto + + + + Create Jami account button + Pulsante Crea account Jami + + + + Push button for Jami account creation start trigger + Pulsante per l'attivazione della creazione dell'account Jami + + + + Create a Jami account + Crea un account Jami + + + + Link device button + Pulsante Collega dispositivo + + + + Push button for device linkage start trigger + Pulsante per l'attivazione dell'avvio del collegamento del dispositivo + + + + Link this device to an account + Collega questo dispositivo ad un account + + + + Create Jami SIP account button + Crea pulsante account SIP Jami + + + + Push button for Jami SIP account creation start trigger + Pulsante per l'attivazione della creazione dell'account SIP Jami + + + + Create a SIP account + Crea un account SIP + + + + Link this device to an existing account + Collega questo dispositivo ad un account esistente + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Ubuntu'; font-size:14px; color:#555555;">To link this device to another account, you first </span><span style=" font-family:'Ubuntu'; font-size:14px; font-weight:600; color:#555555;">need to obtain a PIN</span><span style=" font-family:'Ubuntu'; font-size:14px; color:#555555;"> code. To generate the PIN code:</span></p> +<ol style="margin-top: 0px; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; -qt-list-indent: 1;"><li style=" font-family:'Ubuntu'; font-size:14px; color:#555555;" style=" margin-top:12px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:14px;">Go to the </span><span style=" font-size:14px; font-weight:600;">Account management setting</span><span style=" font-size:14px;"> of a previous device</span></li> +<li style=" font-family:'Ubuntu'; font-size:14px; color:#555555;" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:14px;">Choose the </span><span style=" font-size:14px; font-weight:600;">Jami account</span><span style=" font-size:14px;"> you want to use</span></li> +<li style=" font-family:'Ubuntu'; font-size:14px; color:#555555;" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:14px;">Go to the </span><span style=" font-size:14px; font-weight:600;">Devices</span><span style=" font-size:14px;"> tab</span></li> +<li style=" font-family:'Ubuntu'; font-size:14px; color:#555555;" style=" margin-top:0px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:14px;">Select </span><span style=" font-size:14px; font-weight:600;">Add a device</span></li></ol> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Ubuntu'; font-size:14px; color:#555555;">You will get the necessary PIN to complete this form. The PIN is only valid for </span><span style=" font-family:'Ubuntu'; font-size:14px; font-weight:600; color:#555555;">10 minutes</span><span style=" font-family:'Ubuntu'; font-size:10px; color:#555555;">.</span></p></body></html> + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Ubuntu'; font-size:14px; color:#555555;">Per collegare questo dispositivo a un altro account, per prima cosa</span><span style=" font-family:'Ubuntu'; font-size:14px; font-weight:600; color:#555555;">è necessario ottenere un codice PIN</span><span style=" font-family:'Ubuntu'; font-size:14px; color:#555555;">. Per generare il codice PIN:</span></p> +<ol style="margin-top: 0px; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; -qt-list-indent: 1;"><li style=" font-family:'Ubuntu'; font-size:14px; color:#555555;" style=" margin-top:12px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:14px;">Vai su </span><span style=" font-size:14px; font-weight:600;">Impostazioni di gestione dell'account</span><span style=" font-size:14px;"> di un dispositivo precedente</span></li> +<li style=" font-family:'Ubuntu'; font-size:14px; color:#555555;" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:14px;">Scegli l' </span><span style=" font-size:14px; font-weight:600;">account Jami</span><span style=" font-size:14px;"> che vuoi usare</span></li> +<li style=" font-family:'Ubuntu'; font-size:14px; color:#555555;" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:14px;">Vai alla </span><span style=" font-size:14px; font-weight:600;">scheda</span><span style=" font-size:14px;">dispositivi</span></li> +<li style=" font-family:'Ubuntu'; font-size:14px; color:#555555;" style=" margin-top:0px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:14px;">Seleziona </span><span style=" font-size:14px; font-weight:600;">Aggiungi dispositivo</span></li></ol> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Ubuntu'; font-size:14px; color:#555555;">Riceverai il PIN necessario per completare questo modulo. Il PIN è valido solo per </span><span style=" font-family:'Ubuntu'; font-size:14px; font-weight:600; color:#555555;">10 minuti</span><span style=" font-family:'Ubuntu'; font-size:10px; color:#555555;">.</span></p></body></html> + + + + Enter your pin: + Inserire il pin: + + + + Or import a file: + O importa un file: + + + + Link from exported account archive file + Collegamento dal file di archivio dell'account esportato + + + + + + (None) + (Nessuno) + + + + Password: + Password: + + + + + Profile + Profilo + + + + + Profile name + Nome del profilo + + + + Account + Account + + + + Register your username. +This will reserve the username so that only you can use it. +Your friends will be able to call you with your usename +instead of using your ID. + Registra il tuo nome utente. +Questo riserverà il nome utente in modo che solo tu possa usarlo. +I tuoi amici potranno chiamarti con il tuo nome utente +invece di usare il tuo ID. + + + + Public username checkbox + Casella di controllo nome utente pubblico + + + + Checkbox selecting if the user wants a public username + Selezionare la casella se l'utente desidera un nome utente pubblico + + + + Register public username + Registra nome utente pubblico + + + + Public username edit + Modifica nome utente pubblico + + + + Choose your username + scegli il tuo nome utente + + + + Password text input + Inserimento testo password + + + + Password text entry + Inserimento testo password + + + + + Password + Password + + + + + Password confirmation text input + Inserimento di testo di conferma della password + + + + Confirm password + Conferma password + + + + SIP Account + Account SIP + + + + SIP Server edit + Modifica server SIP + + + + Server + Server + + + + SIP proxy input + Ingresso proxy SIP + + + + SIP proxy text entry + Immissione di testo proxy SIP + + + + Proxy + Proxy + + + + SIP username input + Input del nome utente SIP + + + + SIP Password text entry + Immissione di testo password SIP + + + + Username + Utente + + + + + SIP Password text input + Immissione di testo password SIP + + + + Generating your Jami account… + Generare il tuo account Jami ... + + + + Previous page button + Precedente pulsante della pagina + + + + push button to access previous page of wizard + pulsante per accedere alla pagina precedente della procedura guidata + + + + Previous + Precedente + + + + Cancel account create/link + Annulla creazione/collegamento account + + + + push button to cancel account creation or linking + premere il pulsante per annullare la creazione o il collegamento dell'account + + + + Back + Indietro + + + + Next page Button + Pulsante della pagina successiva + + + + Push button to access next page of wizard + Premere il pulsante per accedere alla pagina successiva della procedura guidata + + + + Next + Prossimo + + + + Open File + Apri File + + + + Jami archive files (*.gz); All files (*) + File di archivio Jami (* gz); Tutti i files (*) + + + + Your account needs to be migrated. Enter your password. + Il tuo account deve essere migrato. Inserisci la tua password. + + + + Migrating your Jami account... + Migrazione del tuo account Jami ... + + + + Importing account archive... + Importazione dell'archivio dell'account ... + + + + Generating your Jami account... + Sto' generando il tuo account Jami ... + + + + Generating your SIP account... + Generazione del tuo account SIP... + + + + Error creating account + Errore nella creazione dell'account + + + + PasswordDialog + + + Change Account Password + Cambia password account + + + + Enter Current Password + Immetti la password corrente + + + + Enter New Password + Inserire una nuova password + + + + Confirm New Password + Conferma la nuova password + + + + Confirm + Conferma + + + + Cancel + Annulla + + + + Current Password Incorrect + Password attuale errata + + + + PhotoBoothDialog + + + Photobooth + Photobooth + + + + PhotoboothWidget + + + Form + Modulo + + + + Photobooth display + Visualizzazione photobooth + + + + Choose File + Scegli un file + + + + Image Files (*.jpg *.jpeg *.png) + File immagine (* .jpg * .jpeg * .png) + + + + PrivateBridging + + + Choose File + Scegli un file + + + + Files (*) + Files (*) + + + + QObject + + + No default mail client found + Nessun client E-Mail di Default + + + + + Edit Device Name + Modifica nome dispositivo + + + + Unlink Device From Account + Scollega il dispositivo dall'account + + + + Save new device name + Salva il nuovo nome del dispositivo + + + + Add as contact + Aggiungi come contatto + + + + RingButton + + + Select folder + Seleziona cartella + + + + SettingsWidget + + + Form + Modulo + + + + Settings + Opzioni + + + + Account + Account + + + + + General + Generale + + + + + Audio / Video + Audio / Video + + + + System + Sistema + + + + Enable desktop notifications + Abilita notifiche desktop + + + + Keep minimized on close + Minimizza alla chiusura + + + + Download folder + Scarica la cartella + + + + Save in + Salva in + + + + Always Recording + Sempre in registrazione + + + + Updates + Aggiornamenti + + + + Check for updates automatically every + Controlla gli aggiornamenti automaticamente ogni + + + + Interval between update checks in days selector + Intervallo tra i controlli di aggiornamento nel selettore giorni + + + + days + giorni + + + + Check for updates now button + Controlla gli aggiornamenti ora col pulsante + + + + Check for updates now + Verifica subito gli aggiornamenti + + + + Password + Password + + + + + Enable + Abilitato + + + + toggle enable notifications + attiva/disattiva le notifiche + + + + Toggle keep minimized on close + Attiva/disattiva mantenimento minimizzato alla chiusura + + + + Call Recordings + Registrazioni delle chiamate + + + + Toggle automatic updates + Attiva/disattiva gli aggiornamenti automatici + + + + Jami Account + Jami account + + + + + Profile + Profilo + + + + + Identity + Indentità + + + + Id + Id + + + + Registered name + Nome registrato + + + + Type here to register a username + Digita qui per registrare un nome utente + + + + Register + Salva + + + + Change Password + Cambia password + + + + Export Account + Esporta account + + + + + Delete Account + Elimina account + + + + Linked Devices + Dispositivi collegati + + + + Link Another Device + Collega un altro dispositivo + + + + Banned Contacts + Contatti vietati + + + + Format + Formato + + + + Video device framerate selector + Selettore framerate dispositivo video + + + + Preview unavailable + Anteprima non disponibile + + + + + Advanced Account Settings + Impostazioni avanzate account + + + + SIP Account + Account SIP + + + + Username + Utente + + + + Hostname + Hostname + + + + Proxy + Proxy + + + + Audio + Audio + + + + Microphone + Microfono + + + + Audio input device selector + Selettore del dispositivo di ingresso audio + + + + Output Device + Dispositivo di Uscita + + + + Choose the output device + Scegli il dispositivo di output + + + + Video + Video + + + + Device + Dispositivo + + + + Video device selector + Selettore dispositivo video + + + + A registered name should not have any spaces and must be at least three letters long + Un nome registrato non deve contenere spazi e deve contenere almeno tre lettere + + + + This name is already taken + Questo nome è già stato scelto + + + + + Enter an alias + Inserisci un alias + + + + Register this name + Registra questo nome + + + + Remove Device + Rimuovi dispositivo + + + + Enter this account's password to confirm the removal of this device + Inserisci la password di questo account per confermare la rimozione di questo dispositivo + + + + Are you sure you wish to remove this device? + Sei sicuro di voler rimuovere questo dispositivo? + + + + Export Account Here + Esporta account qui + + + + Select A Folder For Your Downloads + Seleziona una cartella per i tuoi download + + + + Select A Folder For Your Recordings + Seleziona una cartella per le tue registrazioni + + + + VideoOverlay + + + Call on Hold + Chiamata in attesa... + + + + Hold / Unhold + Pausa / Riprendi + + + + Chat + Chat + + + + Mute Mic + Mutati + + + + Record call + Registra chiamata + + + + Name label + Etichetta Nome + + + + Time elapsed + Tempo trascorso + + + + 00:00 + 00:00 + + + + Hangup + Aggancia + + + + Mute Video + Muta Video + + + + VideoView + + + Share entire screen + Condividi l'intero schermo + + + + Share screen area + Condividi l'area dello schermo + + + + Share file + Condividi file + + + \ No newline at end of file diff --git a/translations/ring_client_windows_ja.ts b/translations/ring_client_windows_ja.ts new file mode 100644 index 00000000..93715fcd --- /dev/null +++ b/translations/ring_client_windows_ja.ts @@ -0,0 +1,1592 @@ + + + AboutDialog + + + + About + アプリについて + + + + about button + + + + + credits button + + + + + Credits + クレジット + + + + Free as in Freedom + + + + + The Microsoft Windows client for Jami. +Jami is a secured and distributed communication software. + + + + + version + バージョン + + + + Created by: + 作成者: + + + + Artwork by: + + + + + Based on the SFLPhone project + + + + + AccountItemDelegate + + + Add Account + アカウントを追加 + + + + AdvancedSIPSettingsWidget + + + Form + + + + + Call Settings + 着信設定 + + + + Auto Answer Calls + 自動通話応答 + + + + Enable Custom Ringtone + カスタム着信音を有効にする + + + + Connectivity + 接続性 + + + + STUN Address + STUNサーバーアドレス + + + + Use STUN + STUNを使用 + + + + Use UPnP + UPnPを使用 + + + + Use TURN + TURNを使用 + + + + TURN Password + TURNのパスワード + + + + TURN Username + TURNのユーザー名 + + + + TURN Address + TURNサーバーアドレス + + + + Media + メディア + + + + Enable Video + ビデオを有効化 + + + + Video Codecs + ビデオコーデック + + + + Audio Codecs + 音声コーデック + + + + Audio Files (*.wav *.ogg *.opus *.mp3 *aiff *wma) + 音声ファイル(*.wav *.ogg *.opus *.mp3 *aiff *wma) + + + + Add a custom ringtone + カスタム着信音を追加 + + + + AdvancedSettingsWidget + + + Form + + + + + Call Settings + 通話設定 + + + + Allow Calls From Untrusted Peers + + + + + Auto Answer Calls + 自動通話応答 + + + + Enable Custom Ringtone + カスタム着信音を有効にする + + + + Add a custom ringtone + カスタム着信音を追加 + + + + Name Server + ネームサーバー + + + + Address + アドレス + + + + OpenDHT Configuration + OpenDHT設定 + + + + Enable Proxy + プロキシを有効にする + + + + Bootstrap + ブートストラップ + + + + Security + セキュリティ + + + + Private Key Password + 秘密鍵のパスワード + + + + User Certificate + ユーザー証明書 + + + + Private Key + 秘密鍵 + + + + CA Certificate + CA証明書 + + + + Connectivity + 接続性 + + + + Use STUN + STUNを使用 + + + + STUN Address + STUNサーバーアドレス + + + + Use UPnP + UPnPを使用 + + + + Use TURN + TURNを使用 + + + + TURN Password + TURNのパスワード + + + + TURN Username + TURNのユーザー名 + + + + TURN Address + TURNサーバーアドレス + + + + Media + メディア + + + + Enable Video + ビデオを有効化 + + + + Audio Codecs + 音声コーデック + + + + Video Codecs + ビデオコーデック + + + + Audio Files (*.wav *.ogg *.opus *.mp3 *aiff *wma) + 音声ファイル(*.wav *.ogg *.opus *.mp3 *aiff *wma) + + + + AnimatedOverlay + + + Form + + + + + BannedItemWidget + + + Form + + + + + name + 名前 + + + + id + + + + + CallWidget + + + Show conversations + 会話を表示 + + + + Conversations + 会話 + + + + Search contact text input + + + + + Jami is free software for universal communication which respects the freedoms and privacy of its users. + Jamiは、世界中のユーザーと繋がることができるユーザーの自由とプライバシーを尊重したフリーソフトウェアです。 + + + + + This is your ID. +Copy and share it with your friends! + + +これがあなたのIDです。 +コピーして友達とシェアしましょう! + + + + + Show ring ID QR code + + + + + Share ring ID button + + + + + Double-click to copy + + + + + Error while generating QR Code + + + + + + best name + + + + + best Id + + + + + Back to homepage button + + + + + Add to contacts + 連絡先に追加 + + + + Show invites + + + + + Invites + + + + + + Find a new or existing contact + 新規・既存の連絡先を検索 + + + + Wants to talk to you! + + + + + Answer incoming call button + + + + + Ignore incoming call button + + + + + Answer + 応答 + + + + Ignore + 無視 + + + + Cancel outgoing call + 発信をキャンセル + + + + Cancel + キャンセル + + + + Start video call + ビデオ通話を開始 + + + + Start audio call + 音声通話を開始 + + + + Clear conversation + 会話履歴を削除 + + + + Remove contact + 連絡先を削除 + + + + Block contact + 連絡先をブロック + + + + Copy number + 番号をコピー + + + + Search your received invitations + 受信した招待を検索 + + + + Contact me on Jami + + + + + My Id is : + + + + + %1 + %1 is the contact username + %1 + + + + %1 + %1 is the contact unique identifier + %1 + + + + Call incoming from %1 + %1 から着信 + + + + DeleteAccountDialog + + + Account deletion + + + + + Do you really want to delete the following account? + + + + + If this account hasn't been exported, or added to another device, it will be irrevocably lost. + + + + + Permanently delete account + アカウントを完全に削除 + + + + Delete + 削除 + + + + Cancel account deletion + + + + + Cancel + キャンセル + + + + DeviceItemWidget + + + Form + + + + + Device Id + + + + + this device + このデバイス + + + + InviteButtonsWidget + + + Accept + 受け入れ + + + + Refuse + 拒否 + + + + Block + ブロック + + + + LinkDeviceDialog + + + Dialog + ダイアログ + + + + Enter your account password + アカウントのパスワードを入力してください + + + + Password + パスワード + + + + Ok + OK + + + + Cancel + キャンセル + + + + Exporting account + アカウントをエクスポート中 + + + + Your PIN is + + + + + PIN + PIN + + + + This pin and the account password should be entered in your device within 10 minutes. + + + + + Close + 閉じる + + + + Link Another Device + 別のデバイスをリンク + + + + Incorrect password + + + + + Something went wrong. +Please try again later. + + + + + MainWindow + + + Settings + 設定 + + + + Exit + 終了 + + + + About + アプリについて + + + + Jami + Jami + + + + NameRegistrationDialog + + + Set Registered Name + + + + + Enter your account password + アカウントのパスワードを入力してください + + + + Password text input + + + + + Password text entry + + + + + Password + パスワード + + + + Register + 登録 + + + + Cancel + キャンセル + + + + Registering Name + + + + + Something went wrong + + + + + Close + 閉じる + + + + Incorrect password + + + + + Network error + ネットワークエラー + + + + NewWizardWidget + + + Form + + + + + Welcome Label + + + + + Welcome to + + + + + Welcome Logo + + + + + Create Jami account button + + + + + Push button for Jami account creation start trigger + + + + + Create a Jami account + Jamiアカウントを作成 + + + + Link device button + + + + + Push button for device linkage start trigger + + + + + Link this device to an account + このデバイスをアカウントへリンク + + + + Create Jami SIP account button + + + + + Push button for Jami SIP account creation start trigger + + + + + Create a SIP account + SIPアカウントを作成 + + + + Link this device to an existing account + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Ubuntu'; font-size:14px; color:#555555;">To link this device to another account, you first </span><span style=" font-family:'Ubuntu'; font-size:14px; font-weight:600; color:#555555;">need to obtain a PIN</span><span style=" font-family:'Ubuntu'; font-size:14px; color:#555555;"> code. To generate the PIN code:</span></p> +<ol style="margin-top: 0px; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; -qt-list-indent: 1;"><li style=" font-family:'Ubuntu'; font-size:14px; color:#555555;" style=" margin-top:12px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:14px;">Go to the </span><span style=" font-size:14px; font-weight:600;">Account management setting</span><span style=" font-size:14px;"> of a previous device</span></li> +<li style=" font-family:'Ubuntu'; font-size:14px; color:#555555;" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:14px;">Choose the </span><span style=" font-size:14px; font-weight:600;">Jami account</span><span style=" font-size:14px;"> you want to use</span></li> +<li style=" font-family:'Ubuntu'; font-size:14px; color:#555555;" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:14px;">Go to the </span><span style=" font-size:14px; font-weight:600;">Devices</span><span style=" font-size:14px;"> tab</span></li> +<li style=" font-family:'Ubuntu'; font-size:14px; color:#555555;" style=" margin-top:0px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:14px;">Select </span><span style=" font-size:14px; font-weight:600;">Add a device</span></li></ol> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Ubuntu'; font-size:14px; color:#555555;">You will get the necessary PIN to complete this form. The PIN is only valid for </span><span style=" font-family:'Ubuntu'; font-size:14px; font-weight:600; color:#555555;">10 minutes</span><span style=" font-family:'Ubuntu'; font-size:10px; color:#555555;">.</span></p></body></html> + + + + + Enter your pin: + PINを入力: + + + + Or import a file: + + + + + Link from exported account archive file + + + + + + + (None) + (なし) + + + + Password: + パスワード: + + + + + Profile + プロフィール + + + + + Profile name + プロフィール名 + + + + Account + アカウント + + + + Register your username. +This will reserve the username so that only you can use it. +Your friends will be able to call you with your usename +instead of using your ID. + + + + + Public username checkbox + + + + + Checkbox selecting if the user wants a public username + + + + + Register public username + 公開ユーザー名を登録 + + + + Public username edit + + + + + Choose your username + ユーザー名を選択 + + + + Password text input + + + + + Password text entry + + + + + + Password + パスワード + + + + + Password confirmation text input + + + + + Confirm password + パスワードの再入力 + + + + SIP Account + SIPアカウント + + + + SIP Server edit + SIPサーバーを編集 + + + + Server + サーバー + + + + SIP proxy input + + + + + SIP proxy text entry + + + + + Proxy + プロキシ + + + + SIP username input + + + + + SIP Password text entry + + + + + Username + ユーザー名 + + + + + SIP Password text input + + + + + Generating your Jami account… + + + + + Previous page button + + + + + push button to access previous page of wizard + + + + + Previous + 戻る + + + + Cancel account create/link + + + + + push button to cancel account creation or linking + + + + + Back + 戻る + + + + Next page Button + + + + + Push button to access next page of wizard + 次のページへ進むにはボタンを押してください + + + + Next + 次へ + + + + Open File + ファイルを開く + + + + Jami archive files (*.gz); All files (*) + + + + + Your account needs to be migrated. Enter your password. + + + + + Migrating your Jami account... + + + + + Importing account archive... + アカウントのアーカイブをインポート中... + + + + Generating your Jami account... + + + + + Generating your SIP account... + + + + + Error creating account + アカウントの作成中にエラーが発生しました + + + + PasswordDialog + + + Change Account Password + パスワードの変更 + + + + Enter Current Password + 現在のパスワードを入力 + + + + Enter New Password + 新しいパスワードを入力 + + + + Confirm New Password + 新しいパスワードを再入力 + + + + Confirm + 確認 + + + + Cancel + キャンセル + + + + Current Password Incorrect + + + + + PhotoBoothDialog + + + Photobooth + + + + + PhotoboothWidget + + + Form + + + + + Photobooth display + + + + + Choose File + ファイルの選択 + + + + Image Files (*.jpg *.jpeg *.png) + + + + + PrivateBridging + + + Choose File + ファイルの選択 + + + + Files (*) + + + + + QObject + + + No default mail client found + + + + + + Edit Device Name + + + + + Unlink Device From Account + + + + + Save new device name + + + + + Add as contact + 連絡先を追加 + + + + RingButton + + + Select folder + フォルダを選択 + + + + SettingsWidget + + + Form + + + + + Settings + 設定 + + + + Account + アカウント + + + + + General + 全般 + + + + + Audio / Video + 音声/ビデオ + + + + System + システム + + + + Enable desktop notifications + デスクトップ通知を有効化 + + + + Keep minimized on close + ウィンドウを閉じたら最小化して待機する + + + + Download folder + ダウンロードフォルダー + + + + Save in + 保存先 + + + + Always Recording + + + + + Updates + アップデート + + + + Check for updates automatically every + + + + + Interval between update checks in days selector + + + + + days + + + + + Check for updates now button + アップデートの確認ボタン + + + + Check for updates now + 今すぐアップデートを確認 + + + + Password + パスワード + + + + + Enable + 有効化 + + + + toggle enable notifications + + + + + Toggle keep minimized on close + + + + + Call Recordings + 通話の録音 + + + + Toggle automatic updates + 自動アップデートの切り替え + + + + Jami Account + Jamiアカウント + + + + + Profile + プロフィール + + + + + Identity + ID + + + + Id + ID + + + + Registered name + + + + + Type here to register a username + + + + + Register + 登録 + + + + Change Password + パスワードの変更 + + + + Export Account + アカウントのエクスポート + + + + + Delete Account + アカウントの削除 + + + + Linked Devices + リンクされたデバイス + + + + Link Another Device + 別のデバイスをリンク + + + + Banned Contacts + 禁止された連絡先 + + + + Format + フォーマット + + + + Video device framerate selector + + + + + Preview unavailable + + + + + + Advanced Account Settings + アカウントの拡張設定 + + + + SIP Account + SIPアカウント + + + + Username + ユーザー名 + + + + Hostname + ホスト名 + + + + Proxy + プロキシ + + + + Audio + 音声 + + + + Microphone + マイク + + + + Audio input device selector + + + + + Output Device + 出力デバイス + + + + Choose the output device + 出力デバイスの選択 + + + + Video + 動画 + + + + Device + デバイス + + + + Video device selector + + + + + A registered name should not have any spaces and must be at least three letters long + + + + + This name is already taken + この名前はすでに使用されています + + + + + Enter an alias + + + + + Register this name + + + + + Remove Device + + + + + Enter this account's password to confirm the removal of this device + + + + + Are you sure you wish to remove this device? + デバイスを取り除いてもよろしいですか? + + + + Export Account Here + + + + + Select A Folder For Your Downloads + ダウンロードフォルダーの選択 + + + + Select A Folder For Your Recordings + 記録フォルダーの選択 + + + + VideoOverlay + + + Call on Hold + + + + + Hold / Unhold + + + + + Chat + チャット + + + + Mute Mic + マイクをミュート + + + + Record call + 通話を録画 + + + + Name label + + + + + Time elapsed + 経過時間 + + + + 00:00 + 00:00 + + + + Hangup + 受話 + + + + Mute Video + 動画オフ + + + + VideoView + + + Share entire screen + + + + + Share screen area + 画面を共有 + + + + Share file + ファイルを共有 + + + \ No newline at end of file diff --git a/translations/ring_client_windows_ko_KR.ts b/translations/ring_client_windows_ko_KR.ts new file mode 100644 index 00000000..48195e9a --- /dev/null +++ b/translations/ring_client_windows_ko_KR.ts @@ -0,0 +1,1589 @@ + + + AboutDialog + + + + About + + + + + about button + + + + + credits button + + + + + Credits + + + + + Free as in Freedom + + + + + The Microsoft Windows client for Jami. +Jami is a secured and distributed communication software. + + + + + version + 버전 + + + + Created by: + + + + + Artwork by: + + + + + Based on the SFLPhone project + SFLPhone 프로젝트 기반 + + + + AccountItemDelegate + + + Add Account + + + + + AdvancedSIPSettingsWidget + + + Form + 서식 + + + + Call Settings + + + + + Auto Answer Calls + + + + + Enable Custom Ringtone + + + + + Connectivity + + + + + STUN Address + + + + + Use STUN + STUN 사용 + + + + Use UPnP + + + + + Use TURN + TURN 사용 + + + + TURN Password + + + + + TURN Username + + + + + TURN Address + + + + + Media + + + + + Enable Video + + + + + Video Codecs + + + + + Audio Codecs + + + + + Audio Files (*.wav *.ogg *.opus *.mp3 *aiff *wma) + + + + + Add a custom ringtone + + + + + AdvancedSettingsWidget + + + Form + 서식 + + + + Call Settings + + + + + Allow Calls From Untrusted Peers + + + + + Auto Answer Calls + + + + + Enable Custom Ringtone + + + + + Add a custom ringtone + + + + + Name Server + + + + + Address + 주소 + + + + OpenDHT Configuration + + + + + Enable Proxy + + + + + Bootstrap + + + + + Security + 보안 + + + + Private Key Password + + + + + User Certificate + + + + + Private Key + + + + + CA Certificate + + + + + Connectivity + + + + + Use STUN + STUN 사용 + + + + STUN Address + + + + + Use UPnP + + + + + Use TURN + TURN 사용 + + + + TURN Password + + + + + TURN Username + + + + + TURN Address + + + + + Media + + + + + Enable Video + + + + + Audio Codecs + + + + + Video Codecs + + + + + Audio Files (*.wav *.ogg *.opus *.mp3 *aiff *wma) + + + + + AnimatedOverlay + + + Form + 서식 + + + + BannedItemWidget + + + Form + 서식 + + + + name + + + + + id + + + + + CallWidget + + + Show conversations + + + + + Conversations + 대화 + + + + Search contact text input + + + + + Jami is free software for universal communication which respects the freedoms and privacy of its users. + + + + + + This is your ID. +Copy and share it with your friends! + + + + + + Show ring ID QR code + + + + + Share ring ID button + + + + + Double-click to copy + 더블클릭으로 복사하기 + + + + Error while generating QR Code + QR 생성 중 오류 + + + + + best name + + + + + best Id + + + + + Back to homepage button + + + + + Add to contacts + 연락처에 추가하기 + + + + Show invites + + + + + Invites + + + + + + Find a new or existing contact + + + + + Wants to talk to you! + 당신과 이야기하고 싶어합니다! + + + + Answer incoming call button + + + + + Ignore incoming call button + + + + + Answer + 응답 + + + + Ignore + 무시 + + + + Cancel outgoing call + + + + + Cancel + 취소 + + + + Start video call + + + + + Start audio call + + + + + Clear conversation + + + + + Remove contact + + + + + Block contact + + + + + Copy number + + + + + Search your received invitations + + + + + Contact me on Jami + + + + + My Id is : + + + + + %1 + %1 is the contact username + + + + + %1 + %1 is the contact unique identifier + + + + + Call incoming from %1 + + + + + DeleteAccountDialog + + + Account deletion + + + + + Do you really want to delete the following account? + + + + + If this account hasn't been exported, or added to another device, it will be irrevocably lost. + + + + + Permanently delete account + + + + + Delete + + + + + Cancel account deletion + + + + + Cancel + 취소 + + + + DeviceItemWidget + + + Form + 서식 + + + + Device Id + + + + + this device + + + + + InviteButtonsWidget + + + Accept + 수락 + + + + Refuse + + + + + Block + + + + + LinkDeviceDialog + + + Dialog + + + + + Enter your account password + + + + + Password + 암호 + + + + Ok + 확인 + + + + Cancel + 취소 + + + + Exporting account + + + + + Your PIN is + + + + + PIN + + + + + This pin and the account password should be entered in your device within 10 minutes. + + + + + Close + + + + + Link Another Device + + + + + Incorrect password + + + + + Something went wrong. +Please try again later. + + + + + MainWindow + + + Settings + 설정 + + + + Exit + 종료 + + + + About + + + + + Jami + + + + + NameRegistrationDialog + + + Set Registered Name + + + + + Enter your account password + + + + + Password text input + + + + + Password text entry + + + + + Password + 암호 + + + + Register + + + + + Cancel + 취소 + + + + Registering Name + + + + + Something went wrong + + + + + Close + + + + + Incorrect password + + + + + Network error + + + + + NewWizardWidget + + + Form + 서식 + + + + Welcome Label + + + + + Welcome to + 환영합니다 + + + + Welcome Logo + + + + + Create Jami account button + + + + + Push button for Jami account creation start trigger + + + + + Create a Jami account + + + + + Link device button + + + + + Push button for device linkage start trigger + + + + + Link this device to an account + 이 장치를 계정에 연결하기 + + + + Create Jami SIP account button + + + + + Push button for Jami SIP account creation start trigger + + + + + Create a SIP account + + + + + Link this device to an existing account + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Ubuntu'; font-size:14px; color:#555555;">To link this device to another account, you first </span><span style=" font-family:'Ubuntu'; font-size:14px; font-weight:600; color:#555555;">need to obtain a PIN</span><span style=" font-family:'Ubuntu'; font-size:14px; color:#555555;"> code. To generate the PIN code:</span></p> +<ol style="margin-top: 0px; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; -qt-list-indent: 1;"><li style=" font-family:'Ubuntu'; font-size:14px; color:#555555;" style=" margin-top:12px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:14px;">Go to the </span><span style=" font-size:14px; font-weight:600;">Account management setting</span><span style=" font-size:14px;"> of a previous device</span></li> +<li style=" font-family:'Ubuntu'; font-size:14px; color:#555555;" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:14px;">Choose the </span><span style=" font-size:14px; font-weight:600;">Jami account</span><span style=" font-size:14px;"> you want to use</span></li> +<li style=" font-family:'Ubuntu'; font-size:14px; color:#555555;" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:14px;">Go to the </span><span style=" font-size:14px; font-weight:600;">Devices</span><span style=" font-size:14px;"> tab</span></li> +<li style=" font-family:'Ubuntu'; font-size:14px; color:#555555;" style=" margin-top:0px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:14px;">Select </span><span style=" font-size:14px; font-weight:600;">Add a device</span></li></ol> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Ubuntu'; font-size:14px; color:#555555;">You will get the necessary PIN to complete this form. The PIN is only valid for </span><span style=" font-family:'Ubuntu'; font-size:14px; font-weight:600; color:#555555;">10 minutes</span><span style=" font-family:'Ubuntu'; font-size:10px; color:#555555;">.</span></p></body></html> + + + + + Enter your pin: + + + + + Or import a file: + + + + + Link from exported account archive file + + + + + + + (None) + + + + + Password: + + + + + + Profile + 프로필 + + + + + Profile name + + + + + Account + 계정 + + + + Register your username. +This will reserve the username so that only you can use it. +Your friends will be able to call you with your usename +instead of using your ID. + + + + + Public username checkbox + + + + + Checkbox selecting if the user wants a public username + + + + + Register public username + + + + + Public username edit + + + + + Choose your username + 사용자명 선택 + + + + Password text input + + + + + Password text entry + + + + + + Password + 암호 + + + + + Password confirmation text input + + + + + Confirm password + 암호 확인 + + + + SIP Account + + + + + SIP Server edit + + + + + Server + + + + + SIP proxy input + + + + + SIP proxy text entry + + + + + Proxy + 프록시 + + + + SIP username input + + + + + SIP Password text entry + + + + + Username + 사용자명 + + + + + SIP Password text input + + + + + Generating your Jami account… + + + + + Previous page button + + + + + push button to access previous page of wizard + + + + + Previous + 이전 + + + + Cancel account create/link + + + + + push button to cancel account creation or linking + + + + + Back + + + + + Next page Button + + + + + Push button to access next page of wizard + + + + + Next + 다음 + + + + Open File + 파일 열기 + + + + Jami archive files (*.gz); All files (*) + + + + + Your account needs to be migrated. Enter your password. + 당신의 계정은 이전이 필요합니다. 암호를 입력하세요. + + + + Migrating your Jami account... + + + + + Importing account archive... + + + + + Generating your Jami account... + + + + + Generating your SIP account... + + + + + Error creating account + + + + + PasswordDialog + + + Change Account Password + + + + + Enter Current Password + + + + + Enter New Password + + + + + Confirm New Password + + + + + Confirm + + + + + Cancel + 취소 + + + + Current Password Incorrect + + + + + PhotoBoothDialog + + + Photobooth + 포토부스 + + + + PhotoboothWidget + + + Form + 서식 + + + + Photobooth display + + + + + Choose File + 파일 선택하기 + + + + Image Files (*.jpg *.jpeg *.png) + + + + + PrivateBridging + + + Choose File + 파일 선택하기 + + + + Files (*) + 파일들 (*) + + + + QObject + + + No default mail client found + 기본 메일 클라이언트를 찾을 수 없습니다. + + + + + Edit Device Name + + + + + Unlink Device From Account + + + + + Save new device name + + + + + Add as contact + + + + + RingButton + + + Select folder + + + + + SettingsWidget + + + Form + 서식 + + + + Settings + 설정 + + + + Account + 계정 + + + + + General + 일반 + + + + + Audio / Video + + + + + System + + + + + Enable desktop notifications + + + + + Keep minimized on close + 닫을 때 최소화 유지하기 + + + + Download folder + + + + + Save in + + + + + Always Recording + + + + + Updates + + + + + Check for updates automatically every + + + + + Interval between update checks in days selector + + + + + days + + + + + Check for updates now button + + + + + Check for updates now + 지금 업데이트 확인하기 + + + + Password + 암호 + + + + + Enable + + + + + toggle enable notifications + + + + + Toggle keep minimized on close + + + + + Call Recordings + + + + + Toggle automatic updates + + + + + Jami Account + + + + + + Profile + 프로필 + + + + + Identity + + + + + Id + + + + + Registered name + + + + + Type here to register a username + + + + + Register + + + + + Change Password + + + + + Export Account + + + + + + Delete Account + + + + + Linked Devices + + + + + Link Another Device + + + + + Banned Contacts + 차단한 연락처 + + + + Format + + + + + Video device framerate selector + + + + + Preview unavailable + + + + + + Advanced Account Settings + + + + + SIP Account + + + + + Username + 사용자명 + + + + Hostname + 호스트명 + + + + Proxy + 프록시 + + + + Audio + + + + + Microphone + + + + + Audio input device selector + + + + + Output Device + 출력 장치 + + + + Choose the output device + + + + + Video + 비디오 + + + + Device + 장치 + + + + Video device selector + + + + + A registered name should not have any spaces and must be at least three letters long + + + + + This name is already taken + + + + + + Enter an alias + + + + + Register this name + + + + + Remove Device + + + + + Enter this account's password to confirm the removal of this device + + + + + Are you sure you wish to remove this device? + + + + + Export Account Here + + + + + Select A Folder For Your Downloads + + + + + Select A Folder For Your Recordings + + + + + VideoOverlay + + + Call on Hold + + + + + Hold / Unhold + 대기 / 대기해제 + + + + Chat + 대화하기 + + + + Mute Mic + 마이크 끄기 + + + + Record call + + + + + Name label + + + + + Time elapsed + 경과한 시간 + + + + 00:00 + + + + + Hangup + 통화종료 + + + + Mute Video + 비디오 숨기기 + + + + VideoView + + + Share entire screen + 전체화면 공유하기 + + + + Share screen area + 화면 영역 공유하기 + + + + Share file + 파일 공유하기 + + + \ No newline at end of file diff --git a/translations/ring_client_windows_lt.ts b/translations/ring_client_windows_lt.ts new file mode 100644 index 00000000..b5eeca88 --- /dev/null +++ b/translations/ring_client_windows_lt.ts @@ -0,0 +1,1606 @@ + + + AboutDialog + + + + About + Apie + + + + about button + + + + + credits button + + + + + Credits + Padėkos + + + + Free as in Freedom + + + + + The Microsoft Windows client for Jami. +Jami is a secured and distributed communication software. + Microsoft Windows kliento programa skirta Jami. +Jami yra apsaugota ir paskirstytoji bendravimo programinė įranga. + + + + version + versija + + + + Created by: + Sukūrė: + + + + Artwork by: + Apipavidalino: + + + + Based on the SFLPhone project + Pagrįsta SFLPhone projektu + + + + AccountItemDelegate + + + Add Account + Pridėti paskyrą + + + + AdvancedSIPSettingsWidget + + + Form + Forma + + + + Call Settings + Skambučio nustatymai + + + + Auto Answer Calls + Automatiškai atsiliepti į skambučius + + + + Enable Custom Ringtone + Įjungti tinkintą skambučio melodiją + + + + Connectivity + Jungiamumas + + + + STUN Address + STUN adresas + + + + Use STUN + Naudoti STUN + + + + Use UPnP + Naudoti UPnP + + + + Use TURN + Naudoti TURN + + + + TURN Password + TURN slaptažodis + + + + TURN Username + TURN naudotojo vardas + + + + TURN Address + TURN adresas + + + + Media + Medija + + + + Enable Video + Įjungti vaizdą + + + + Video Codecs + Vaizdo kodekai + + + + Audio Codecs + Garso kodekai + + + + Audio Files (*.wav *.ogg *.opus *.mp3 *aiff *wma) + Garso failai (*.wav *.ogg *.opus *.mp3 *aiff *wma) + + + + Add a custom ringtone + Pridėti tinkintą skambučio melodiją + + + + AdvancedSettingsWidget + + + Form + Forma + + + + Call Settings + Skambučio nustatymai + + + + Allow Calls From Untrusted Peers + + + + + Auto Answer Calls + Automatiškai atsiliepti į skambučius + + + + Enable Custom Ringtone + Įjungti tinkintą skambučio melodiją + + + + Add a custom ringtone + Pridėti tinkintą skambučio melodiją + + + + Name Server + Vardų serveris + + + + Address + Adresas + + + + OpenDHT Configuration + OpenDHT konfigūracija + + + + Enable Proxy + Įjungti įgaliotąjį serverį + + + + Bootstrap + Pradinė įkeltis + + + + Security + Saugumas + + + + Private Key Password + Privačiojo rakto slaptažodis + + + + User Certificate + Naudotojo liudijimas + + + + Private Key + Privatusis raktas + + + + CA Certificate + LĮ liudijimas + + + + Connectivity + Jungiamumas + + + + Use STUN + Naudoti STUN + + + + STUN Address + STUN adresas + + + + Use UPnP + Naudoti UPnP + + + + Use TURN + Naudoti TURN + + + + TURN Password + TURN slaptažodis + + + + TURN Username + TURN naudotojo vardas + + + + TURN Address + TURN adresas + + + + Media + Medija + + + + Enable Video + Įjungti vaizdą + + + + Audio Codecs + Garso kodekai + + + + Video Codecs + Vaizdo kodekai + + + + Audio Files (*.wav *.ogg *.opus *.mp3 *aiff *wma) + Garso failai (*.wav *.ogg *.opus *.mp3 *aiff *wma) + + + + AnimatedOverlay + + + Form + Forma + + + + BannedItemWidget + + + Form + Forma + + + + name + + + + + id + + + + + CallWidget + + + Show conversations + Rodyti pokalbius + + + + Conversations + Pokalbiai + + + + Search contact text input + Ieškoti adresato + + + + Jami is free software for universal communication which respects the freedoms and privacy of its users. + Jami yra visuotiniam bendravimui skirta laisva programinė įranga, kuri gerbia savo naudotojų laisves ir privatumą. + + + + + This is your ID. +Copy and share it with your friends! + + + Tai yra jūsų ID. +Nukopijuokite jį ir dalinkitės juo su savo draugais! + + + + + Show ring ID QR code + + + + + Share ring ID button + + + + + Double-click to copy + Spustelėkite du kartus, norėdami nukopijuoti + + + + Error while generating QR Code + Klaida, kuriant QR kodą + + + + + best name + + + + + best Id + + + + + Back to homepage button + + + + + Add to contacts + Pridėti prie adresatų + + + + Show invites + + + + + Invites + + + + + + Find a new or existing contact + Rasti naują ar esamą adresatą + + + + Wants to talk to you! + Nori su jumis pakalbėti! + + + + Answer incoming call button + + + + + Ignore incoming call button + + + + + Answer + Atsiliepti + + + + Ignore + Nepaisyti + + + + Cancel outgoing call + + + + + Cancel + Atsisakyti + + + + Start video call + Pradėti vaizdo skambutį + + + + Start audio call + Pradėti garso skambutį + + + + Clear conversation + Išvalyti pokalbį + + + + Remove contact + Šalinti adresatą + + + + Block contact + Užblokuoti adresatą + + + + Copy number + Kopijuoti numerį + + + + Search your received invitations + + + + + Contact me on Jami + + + + + My Id is : + + + + + %1 + %1 is the contact username + %1 + + + + %1 + %1 is the contact unique identifier + %1 + + + + Call incoming from %1 + Gaunamasis skambutis nuo %1 + + + + DeleteAccountDialog + + + Account deletion + Paskyros ištrynimas + + + + Do you really want to delete the following account? + Ar tikrai norite ištrinti šią paskyrą? + + + + If this account hasn't been exported, or added to another device, it will be irrevocably lost. + Jeigu ši paskyra nebuvo eksportuota ar pridėta į kitą įrenginį, ji bus negrįžtamai prarasta. + + + + Permanently delete account + Ištrinti paskyrą visiems laikams + + + + Delete + Ištrinti + + + + Cancel account deletion + Atsisakyti paskyros ištrynimo + + + + Cancel + Atsisakyti + + + + DeviceItemWidget + + + Form + Forma + + + + Device Id + Įrenginio ID + + + + this device + šis įrenginys + + + + InviteButtonsWidget + + + Accept + Priimti + + + + Refuse + Atmesti + + + + Block + Užblokuoti + + + + LinkDeviceDialog + + + Dialog + Dialogas + + + + Enter your account password + Įveskite savo paskyros slaptažodį + + + + Password + Slaptažodis + + + + Ok + Gerai + + + + Cancel + Atsisakyti + + + + Exporting account + Eksportuojama paskyra + + + + Your PIN is + Jūsų PIN yra + + + + PIN + PIN + + + + This pin and the account password should be entered in your device within 10 minutes. + + + + + Close + Užverti + + + + Link Another Device + Susieti kitą įrenginį + + + + Incorrect password + Neteisingas slaptažodis + + + + Something went wrong. +Please try again later. + Kažkas nutiko. +Vėliau bandykite dar kartą. + + + + MainWindow + + + Settings + Nustatymai + + + + Exit + Išeiti + + + + About + Apie + + + + Jami + Jami + + + + NameRegistrationDialog + + + Set Registered Name + Nustatyti registruotą vardą + + + + Enter your account password + Įveskite savo paskyros slaptažodį + + + + Password text input + + + + + Password text entry + + + + + Password + Slaptažodis + + + + Register + Registruoti + + + + Cancel + Atsisakyti + + + + Registering Name + + + + + Something went wrong + Kažkas nutiko + + + + Close + Užverti + + + + Incorrect password + Neteisingas slaptažodis + + + + Network error + Tinklo klaida + + + + NewWizardWidget + + + Form + Forma + + + + Welcome Label + + + + + Welcome to + Sveiki atvykę į + + + + Welcome Logo + + + + + Create Jami account button + Susikurkite Jami paskyrą + + + + Push button for Jami account creation start trigger + + + + + Create a Jami account + Susikurti Jami paskyrą + + + + Link device button + Susiekite įrenginį + + + + Push button for device linkage start trigger + + + + + Link this device to an account + Susieti šį įrenginį su paskyra + + + + Create Jami SIP account button + + + + + Push button for Jami SIP account creation start trigger + + + + + Create a SIP account + + + + + Link this device to an existing account + Susieti šį įrenginį su esama paskyra + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Ubuntu'; font-size:14px; color:#555555;">To link this device to another account, you first </span><span style=" font-family:'Ubuntu'; font-size:14px; font-weight:600; color:#555555;">need to obtain a PIN</span><span style=" font-family:'Ubuntu'; font-size:14px; color:#555555;"> code. To generate the PIN code:</span></p> +<ol style="margin-top: 0px; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; -qt-list-indent: 1;"><li style=" font-family:'Ubuntu'; font-size:14px; color:#555555;" style=" margin-top:12px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:14px;">Go to the </span><span style=" font-size:14px; font-weight:600;">Account management setting</span><span style=" font-size:14px;"> of a previous device</span></li> +<li style=" font-family:'Ubuntu'; font-size:14px; color:#555555;" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:14px;">Choose the </span><span style=" font-size:14px; font-weight:600;">Jami account</span><span style=" font-size:14px;"> you want to use</span></li> +<li style=" font-family:'Ubuntu'; font-size:14px; color:#555555;" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:14px;">Go to the </span><span style=" font-size:14px; font-weight:600;">Devices</span><span style=" font-size:14px;"> tab</span></li> +<li style=" font-family:'Ubuntu'; font-size:14px; color:#555555;" style=" margin-top:0px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:14px;">Select </span><span style=" font-size:14px; font-weight:600;">Add a device</span></li></ol> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Ubuntu'; font-size:14px; color:#555555;">You will get the necessary PIN to complete this form. The PIN is only valid for </span><span style=" font-family:'Ubuntu'; font-size:14px; font-weight:600; color:#555555;">10 minutes</span><span style=" font-family:'Ubuntu'; font-size:10px; color:#555555;">.</span></p></body></html> + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Ubuntu'; font-size:14px; color:#555555;">Norėdami susieti šį įrenginį su kita paskyra, iš pradžių, </span><span style=" font-family:'Ubuntu'; font-size:14px; font-weight:600; color:#555555;">turite gauti PIN</span><span style=" font-family:'Ubuntu'; font-size:14px; color:#555555;"> kodą. Norėdami generuoti PIN kodą:</span></p> +<ol style="margin-top: 0px; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; -qt-list-indent: 1;"><li style=" font-family:'Ubuntu'; font-size:14px; color:#555555;" style=" margin-top:12px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:14px;">Ankstesniajame įrenginyje pereikite į </span><span style=" font-size:14px; font-weight:600;">paskyros tvarkymo nustatymus</span><span style=" font-size:14px;"></span></li> +<li style=" font-family:'Ubuntu'; font-size:14px; color:#555555;" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:14px;">Pasirinkite norimą naudoti </span><span style=" font-size:14px; font-weight:600;">Jami paskyrą</span><span style=" font-size:14px;"></span></li> +<li style=" font-family:'Ubuntu'; font-size:14px; color:#555555;" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:14px;">Pereikite į </span><span style=" font-size:14px; font-weight:600;">Įrenginių</span><span style=" font-size:14px;"> kortelę</span></li> +<li style=" font-family:'Ubuntu'; font-size:14px; color:#555555;" style=" margin-top:0px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:14px;">Pasirinkite </span><span style=" font-size:14px; font-weight:600;">Pridėti įrenginį</span></li></ol> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Ubuntu'; font-size:14px; color:#555555;">Taip gausite šiai formai reikalingą PIN kodą. PIN galios tik </span><span style=" font-family:'Ubuntu'; font-size:14px; font-weight:600; color:#555555;">10 minučių</span><span style=" font-family:'Ubuntu'; font-size:10px; color:#555555;">.</span></p></body></html> + + + + Enter your pin: + Įveskite savo pin: + + + + Or import a file: + Arba importuokite failą: + + + + Link from exported account archive file + Susieti iš eksportuotos paskyros archyvo failo + + + + + + (None) + (Nėra) + + + + Password: + Slaptažodis: + + + + + Profile + Profilis + + + + + Profile name + Profilio pavadinimas + + + + Account + Paskyra + + + + Register your username. +This will reserve the username so that only you can use it. +Your friends will be able to call you with your usename +instead of using your ID. + Užregistruokite savo naudotojo vardą. +Tai rezervuos naudotojo vardą ir tokiu būdu tik jūs +galėsite jį naudoti. Jūsų draugai galės jums skambinti, +vietoj jūsų ID naudodami jūsų naudotojo vardą. + + + + Public username checkbox + + + + + Checkbox selecting if the user wants a public username + + + + + Register public username + Registruoti viešąjį naudotojo vardą + + + + Public username edit + + + + + Choose your username + Pasirinkite savo naudotojo vardą + + + + Password text input + + + + + Password text entry + + + + + + Password + Slaptažodis + + + + + Password confirmation text input + + + + + Confirm password + Patvirtinkite slaptažodį + + + + SIP Account + SIP paskyra + + + + SIP Server edit + + + + + Server + Serveris + + + + SIP proxy input + + + + + SIP proxy text entry + + + + + Proxy + Įgaliotasis serveris + + + + SIP username input + + + + + SIP Password text entry + + + + + Username + Naudotojo vardas + + + + + SIP Password text input + + + + + Generating your Jami account… + Kuriama jūsų Jami paskyra… + + + + Previous page button + Ankstesnis puslapis + + + + push button to access previous page of wizard + + + + + Previous + Ankstesnis + + + + Cancel account create/link + + + + + push button to cancel account creation or linking + + + + + Back + Atgal + + + + Next page Button + Kitas puslapis + + + + Push button to access next page of wizard + + + + + Next + Kitas + + + + Open File + Atverti failą + + + + Jami archive files (*.gz); All files (*) + Jami archyvų failai (*.gz); Visi failai (*) + + + + Your account needs to be migrated. Enter your password. + Jūsų paskyra turi būti perkelta. Įveskite savo slaptažodį. + + + + Migrating your Jami account... + Perkeliama jūsų Jami paskyra... + + + + Importing account archive... + Importuojamas paskyros archyvas... + + + + Generating your Jami account... + Kuriama jūsų Jami paskyra... + + + + Generating your SIP account... + + + + + Error creating account + Klaida, kuriant paskyrą + + + + PasswordDialog + + + Change Account Password + Pakeisti paskyros slaptažodį + + + + Enter Current Password + Įveskite dabartinį slaptažodį + + + + Enter New Password + Įveskite naują slaptažodį + + + + Confirm New Password + Pakartokite naują slaptažodį + + + + Confirm + Patvirtinti + + + + Cancel + Atsisakyti + + + + Current Password Incorrect + Dabartinis slaptažodis neteisingas + + + + PhotoBoothDialog + + + Photobooth + Nuotraukų budelė + + + + PhotoboothWidget + + + Form + Forma + + + + Photobooth display + Nuotraukų budelės rodinys + + + + Choose File + Pasirinkti failą + + + + Image Files (*.jpg *.jpeg *.png) + Paveikslų failai (*.jpg *.jpeg *.png) + + + + PrivateBridging + + + Choose File + Pasirinkti failą + + + + Files (*) + Failai (*) + + + + QObject + + + No default mail client found + Numatytoji pašto kliento programa nerasta + + + + + Edit Device Name + Taisyti įrenginio pavadinimą + + + + Unlink Device From Account + Atsieti įrenginį nuo paskyros + + + + Save new device name + + + + + Add as contact + + + + + RingButton + + + Select folder + Pasirinkti aplanką + + + + SettingsWidget + + + Form + Forma + + + + Settings + Nustatymai + + + + Account + Paskyra + + + + + General + Bendra + + + + + Audio / Video + Garsas / Vaizdas + + + + System + Sistema + + + + Enable desktop notifications + Įjungti darbalaukio pranešimus + + + + Keep minimized on close + Užvėrus, palikti suskleistą + + + + Download folder + Atsiuntimų aplankas + + + + Save in + Įrašyti į + + + + Always Recording + Visada įrašinėti + + + + Updates + Atnaujinimai + + + + Check for updates automatically every + Automatiškai tikrinti ar yra atnaujinimų kas + + + + Interval between update checks in days selector + + + + + days + d. + + + + Check for updates now button + + + + + Check for updates now + Tikrinti dabar ar yra atnaujinimų + + + + Password + Slaptažodis + + + + + Enable + Įjungti + + + + toggle enable notifications + + + + + Toggle keep minimized on close + + + + + Call Recordings + + + + + Toggle automatic updates + + + + + Jami Account + Jami paskyra + + + + + Profile + Profilis + + + + + Identity + Tapatybė + + + + Id + Id + + + + Registered name + + + + + Type here to register a username + Rašykite, norėdami registruoti vardą + + + + Register + Registruoti + + + + Change Password + Pakeisti slaptažodį + + + + Export Account + Eksportuoti paskyrą + + + + + Delete Account + Ištrinti paskyrą + + + + Linked Devices + Susieti įrenginiai + + + + Link Another Device + Susieti kitą įrenginį + + + + Banned Contacts + Užblokuoti adresatai + + + + Format + Formatas + + + + Video device framerate selector + + + + + Preview unavailable + Peržiūra neprieinama + + + + + Advanced Account Settings + Išplėstiniai paskyros nustatymai + + + + SIP Account + SIP paskyra + + + + Username + Naudotojo vardas + + + + Hostname + Kompiuterio vardas + + + + Proxy + Įgaliotasis serveris + + + + Audio + Garsas + + + + Microphone + Mikrofonas + + + + Audio input device selector + + + + + Output Device + Išvesties įrenginys + + + + Choose the output device + + + + + Video + Vaizdas + + + + Device + Įrenginys + + + + Video device selector + + + + + A registered name should not have any spaces and must be at least three letters long + Registruotame varde negali būti tarpų ir jis privalo būti bent 3 raidžių ilgio + + + + This name is already taken + Šis vardas jau yra užimtas + + + + + Enter an alias + + + + + Register this name + Registruoti šį vardą + + + + Remove Device + Šalinti įrenginį + + + + Enter this account's password to confirm the removal of this device + Įveskite šios paskyros slaptažodį, kad patvirtintumėte šio įrenginio šalinimą + + + + Are you sure you wish to remove this device? + Ar tikrai norite pašalinti šį įrenginį? + + + + Export Account Here + Eksportuoti paskyrą čia + + + + Select A Folder For Your Downloads + Pasirinkite atsiuntimų aplanką + + + + Select A Folder For Your Recordings + Pasirinkite įrašų aplanką + + + + VideoOverlay + + + Call on Hold + + + + + Hold / Unhold + + + + + Chat + Pokalbis + + + + Mute Mic + Išjungti mikrofoną + + + + Record call + Įrašyti skambutį + + + + Name label + Vardo etiketė + + + + Time elapsed + Praėjęs laikas + + + + 00:00 + 00:00 + + + + Hangup + Padėti ragelį + + + + Mute Video + Išjungti vaizdą + + + + VideoView + + + Share entire screen + Bendrinti visą ekraną + + + + Share screen area + Bendrinti ekrano sritį + + + + Share file + Bendrinti failą + + + \ No newline at end of file diff --git a/translations/ring_client_windows_ms.ts b/translations/ring_client_windows_ms.ts new file mode 100644 index 00000000..38a3f477 --- /dev/null +++ b/translations/ring_client_windows_ms.ts @@ -0,0 +1,1589 @@ + + + AboutDialog + + + + About + Tentang + + + + about button + + + + + credits button + + + + + Credits + Kredit + + + + Free as in Freedom + + + + + The Microsoft Windows client for Jami. +Jami is a secured and distributed communication software. + + + + + version + versi + + + + Created by: + Dicipta oleh: + + + + Artwork by: + Kerja seni oleh: + + + + Based on the SFLPhone project + Berdasarkan projek + + + + AccountItemDelegate + + + Add Account + + + + + AdvancedSIPSettingsWidget + + + Form + + + + + Call Settings + + + + + Auto Answer Calls + + + + + Enable Custom Ringtone + + + + + Connectivity + + + + + STUN Address + + + + + Use STUN + + + + + Use UPnP + + + + + Use TURN + Guna TURN + + + + TURN Password + + + + + TURN Username + + + + + TURN Address + + + + + Media + Media + + + + Enable Video + Aktifkan panggilan video + + + + Video Codecs + + + + + Audio Codecs + + + + + Audio Files (*.wav *.ogg *.opus *.mp3 *aiff *wma) + + + + + Add a custom ringtone + + + + + AdvancedSettingsWidget + + + Form + + + + + Call Settings + + + + + Allow Calls From Untrusted Peers + + + + + Auto Answer Calls + + + + + Enable Custom Ringtone + + + + + Add a custom ringtone + + + + + Name Server + + + + + Address + + + + + OpenDHT Configuration + + + + + Enable Proxy + + + + + Bootstrap + Bootstrap + + + + Security + Penyulitan + + + + Private Key Password + Kata laluan untuk fail Private Key + + + + User Certificate + + + + + Private Key + + + + + CA Certificate + + + + + Connectivity + + + + + Use STUN + + + + + STUN Address + + + + + Use UPnP + + + + + Use TURN + Guna TURN + + + + TURN Password + + + + + TURN Username + + + + + TURN Address + + + + + Media + Media + + + + Enable Video + Aktifkan panggilan video + + + + Audio Codecs + + + + + Video Codecs + + + + + Audio Files (*.wav *.ogg *.opus *.mp3 *aiff *wma) + + + + + AnimatedOverlay + + + Form + + + + + BannedItemWidget + + + Form + + + + + name + + + + + id + + + + + CallWidget + + + Show conversations + + + + + Conversations + + + + + Search contact text input + + + + + Jami is free software for universal communication which respects the freedoms and privacy of its users. + + + + + + This is your ID. +Copy and share it with your friends! + + + + + + Show ring ID QR code + + + + + Share ring ID button + + + + + Double-click to copy + + + + + Error while generating QR Code + + + + + + best name + + + + + best Id + + + + + Back to homepage button + + + + + Add to contacts + Tambahkan sebagai kenalan + + + + Show invites + + + + + Invites + + + + + + Find a new or existing contact + + + + + Wants to talk to you! + + + + + Answer incoming call button + + + + + Ignore incoming call button + + + + + Answer + + + + + Ignore + + + + + Cancel outgoing call + + + + + Cancel + Batal + + + + Start video call + + + + + Start audio call + + + + + Clear conversation + + + + + Remove contact + + + + + Block contact + + + + + Copy number + Salin nombor + + + + Search your received invitations + + + + + Contact me on Jami + + + + + My Id is : + + + + + %1 + %1 is the contact username + + + + + %1 + %1 is the contact unique identifier + + + + + Call incoming from %1 + + + + + DeleteAccountDialog + + + Account deletion + + + + + Do you really want to delete the following account? + + + + + If this account hasn't been exported, or added to another device, it will be irrevocably lost. + + + + + Permanently delete account + + + + + Delete + Hapus + + + + Cancel account deletion + + + + + Cancel + Batal + + + + DeviceItemWidget + + + Form + + + + + Device Id + + + + + this device + + + + + InviteButtonsWidget + + + Accept + Terima + + + + Refuse + + + + + Block + + + + + LinkDeviceDialog + + + Dialog + + + + + Enter your account password + + + + + Password + Kara laluan + + + + Ok + + + + + Cancel + Batal + + + + Exporting account + + + + + Your PIN is + + + + + PIN + + + + + This pin and the account password should be entered in your device within 10 minutes. + + + + + Close + + + + + Link Another Device + + + + + Incorrect password + + + + + Something went wrong. +Please try again later. + + + + + MainWindow + + + Settings + Tetapan + + + + Exit + + + + + About + Tentang + + + + Jami + + + + + NameRegistrationDialog + + + Set Registered Name + + + + + Enter your account password + + + + + Password text input + + + + + Password text entry + + + + + Password + Kara laluan + + + + Register + Daftar + + + + Cancel + Batal + + + + Registering Name + + + + + Something went wrong + + + + + Close + + + + + Incorrect password + + + + + Network error + Rangkaian gagal + + + + NewWizardWidget + + + Form + + + + + Welcome Label + + + + + Welcome to + + + + + Welcome Logo + + + + + Create Jami account button + + + + + Push button for Jami account creation start trigger + + + + + Create a Jami account + + + + + Link device button + + + + + Push button for device linkage start trigger + + + + + Link this device to an account + Sambungkan perangkat ini dengan akaun + + + + Create Jami SIP account button + + + + + Push button for Jami SIP account creation start trigger + + + + + Create a SIP account + + + + + Link this device to an existing account + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Ubuntu'; font-size:14px; color:#555555;">To link this device to another account, you first </span><span style=" font-family:'Ubuntu'; font-size:14px; font-weight:600; color:#555555;">need to obtain a PIN</span><span style=" font-family:'Ubuntu'; font-size:14px; color:#555555;"> code. To generate the PIN code:</span></p> +<ol style="margin-top: 0px; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; -qt-list-indent: 1;"><li style=" font-family:'Ubuntu'; font-size:14px; color:#555555;" style=" margin-top:12px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:14px;">Go to the </span><span style=" font-size:14px; font-weight:600;">Account management setting</span><span style=" font-size:14px;"> of a previous device</span></li> +<li style=" font-family:'Ubuntu'; font-size:14px; color:#555555;" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:14px;">Choose the </span><span style=" font-size:14px; font-weight:600;">Jami account</span><span style=" font-size:14px;"> you want to use</span></li> +<li style=" font-family:'Ubuntu'; font-size:14px; color:#555555;" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:14px;">Go to the </span><span style=" font-size:14px; font-weight:600;">Devices</span><span style=" font-size:14px;"> tab</span></li> +<li style=" font-family:'Ubuntu'; font-size:14px; color:#555555;" style=" margin-top:0px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:14px;">Select </span><span style=" font-size:14px; font-weight:600;">Add a device</span></li></ol> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Ubuntu'; font-size:14px; color:#555555;">You will get the necessary PIN to complete this form. The PIN is only valid for </span><span style=" font-family:'Ubuntu'; font-size:14px; font-weight:600; color:#555555;">10 minutes</span><span style=" font-family:'Ubuntu'; font-size:10px; color:#555555;">.</span></p></body></html> + + + + + Enter your pin: + + + + + Or import a file: + + + + + Link from exported account archive file + + + + + + + (None) + + + + + Password: + + + + + + Profile + + + + + + Profile name + + + + + Account + Akaun + + + + Register your username. +This will reserve the username so that only you can use it. +Your friends will be able to call you with your usename +instead of using your ID. + + + + + Public username checkbox + + + + + Checkbox selecting if the user wants a public username + + + + + Register public username + + + + + Public username edit + + + + + Choose your username + + + + + Password text input + + + + + Password text entry + + + + + + Password + Kara laluan + + + + + Password confirmation text input + + + + + Confirm password + Sahkan kata laluan + + + + SIP Account + + + + + SIP Server edit + + + + + Server + + + + + SIP proxy input + + + + + SIP proxy text entry + + + + + Proxy + Proksi + + + + SIP username input + + + + + SIP Password text entry + + + + + Username + Nama pengguna + + + + + SIP Password text input + + + + + Generating your Jami account… + + + + + Previous page button + + + + + push button to access previous page of wizard + + + + + Previous + + + + + Cancel account create/link + + + + + push button to cancel account creation or linking + + + + + Back + + + + + Next page Button + + + + + Push button to access next page of wizard + + + + + Next + + + + + Open File + + + + + Jami archive files (*.gz); All files (*) + + + + + Your account needs to be migrated. Enter your password. + + + + + Migrating your Jami account... + + + + + Importing account archive... + + + + + Generating your Jami account... + + + + + Generating your SIP account... + + + + + Error creating account + Gagal mencipta akaun + + + + PasswordDialog + + + Change Account Password + + + + + Enter Current Password + + + + + Enter New Password + + + + + Confirm New Password + + + + + Confirm + + + + + Cancel + Batal + + + + Current Password Incorrect + + + + + PhotoBoothDialog + + + Photobooth + + + + + PhotoboothWidget + + + Form + + + + + Photobooth display + + + + + Choose File + + + + + Image Files (*.jpg *.jpeg *.png) + + + + + PrivateBridging + + + Choose File + + + + + Files (*) + + + + + QObject + + + No default mail client found + + + + + + Edit Device Name + + + + + Unlink Device From Account + + + + + Save new device name + + + + + Add as contact + + + + + RingButton + + + Select folder + + + + + SettingsWidget + + + Form + + + + + Settings + Tetapan + + + + Account + Akaun + + + + + General + Utama + + + + + Audio / Video + + + + + System + Sistem + + + + Enable desktop notifications + + + + + Keep minimized on close + + + + + Download folder + + + + + Save in + + + + + Always Recording + + + + + Updates + + + + + Check for updates automatically every + + + + + Interval between update checks in days selector + + + + + days + + + + + Check for updates now button + + + + + Check for updates now + + + + + Password + Kara laluan + + + + + Enable + + + + + toggle enable notifications + + + + + Toggle keep minimized on close + + + + + Call Recordings + + + + + Toggle automatic updates + + + + + Jami Account + + + + + + Profile + + + + + + Identity + + + + + Id + + + + + Registered name + + + + + Type here to register a username + + + + + Register + Daftar + + + + Change Password + + + + + Export Account + + + + + + Delete Account + + + + + Linked Devices + + + + + Link Another Device + + + + + Banned Contacts + + + + + Format + + + + + Video device framerate selector + + + + + Preview unavailable + + + + + + Advanced Account Settings + + + + + SIP Account + + + + + Username + Nama pengguna + + + + Hostname + Alamat server + + + + Proxy + Proksi + + + + Audio + Bunyi + + + + Microphone + + + + + Audio input device selector + + + + + Output Device + + + + + Choose the output device + + + + + Video + Video + + + + Device + + + + + Video device selector + + + + + A registered name should not have any spaces and must be at least three letters long + + + + + This name is already taken + + + + + + Enter an alias + + + + + Register this name + + + + + Remove Device + + + + + Enter this account's password to confirm the removal of this device + + + + + Are you sure you wish to remove this device? + + + + + Export Account Here + + + + + Select A Folder For Your Downloads + + + + + Select A Folder For Your Recordings + + + + + VideoOverlay + + + Call on Hold + + + + + Hold / Unhold + + + + + Chat + + + + + Mute Mic + + + + + Record call + + + + + Name label + + + + + Time elapsed + + + + + 00:00 + + + + + Hangup + + + + + Mute Video + + + + + VideoView + + + Share entire screen + + + + + Share screen area + + + + + Share file + + + + \ No newline at end of file diff --git a/translations/ring_client_windows_nb.ts b/translations/ring_client_windows_nb.ts new file mode 100644 index 00000000..8a151969 --- /dev/null +++ b/translations/ring_client_windows_nb.ts @@ -0,0 +1,1589 @@ + + + AboutDialog + + + + About + Om + + + + about button + om-knapp + + + + credits button + bidragsytere-knapp + + + + Credits + Bidragsytere + + + + Free as in Freedom + + + + + The Microsoft Windows client for Jami. +Jami is a secured and distributed communication software. + + + + + version + versjon + + + + Created by: + Opprettet av: + + + + Artwork by: + Omslagskunst av: + + + + Based on the SFLPhone project + Basert på SFLPhone-prosjektet + + + + AccountItemDelegate + + + Add Account + + + + + AdvancedSIPSettingsWidget + + + Form + Skjema + + + + Call Settings + + + + + Auto Answer Calls + + + + + Enable Custom Ringtone + + + + + Connectivity + Forbindelsesstatus + + + + STUN Address + + + + + Use STUN + Bruk STUN + + + + Use UPnP + + + + + Use TURN + Bruk TURN + + + + TURN Password + + + + + TURN Username + + + + + TURN Address + + + + + Media + Media + + + + Enable Video + Aktiver video + + + + Video Codecs + Video-kodeker + + + + Audio Codecs + Lydkodeker + + + + Audio Files (*.wav *.ogg *.opus *.mp3 *aiff *wma) + + + + + Add a custom ringtone + + + + + AdvancedSettingsWidget + + + Form + Skjema + + + + Call Settings + + + + + Allow Calls From Untrusted Peers + + + + + Auto Answer Calls + + + + + Enable Custom Ringtone + + + + + Add a custom ringtone + + + + + Name Server + + + + + Address + Adresse + + + + OpenDHT Configuration + + + + + Enable Proxy + Skru på mellomtjener + + + + Bootstrap + Bootstrap + + + + Security + Sikkerhet + + + + Private Key Password + Privat nøkkel-passord + + + + User Certificate + Brukersertifikat + + + + Private Key + + + + + CA Certificate + + + + + Connectivity + Forbindelsesstatus + + + + Use STUN + Bruk STUN + + + + STUN Address + + + + + Use UPnP + + + + + Use TURN + Bruk TURN + + + + TURN Password + + + + + TURN Username + + + + + TURN Address + + + + + Media + Media + + + + Enable Video + Aktiver video + + + + Audio Codecs + Lydkodeker + + + + Video Codecs + Video-kodeker + + + + Audio Files (*.wav *.ogg *.opus *.mp3 *aiff *wma) + + + + + AnimatedOverlay + + + Form + Skjema + + + + BannedItemWidget + + + Form + Skjema + + + + name + + + + + id + + + + + CallWidget + + + Show conversations + + + + + Conversations + Samtaler + + + + Search contact text input + Søk etter kontakttekst -inndata + + + + Jami is free software for universal communication which respects the freedoms and privacy of its users. + Jami er fri programvare for allsidig kommunikasjon som respekterer brukernes frihet og retten til privatliv. + + + + + This is your ID. +Copy and share it with your friends! + + + + + + Show ring ID QR code + Vis QR-kode for ring ID + + + + Share ring ID button + Del ring ID -knapp + + + + Double-click to copy + Dobbeltklikk for å kopiere + + + + Error while generating QR Code + Feil ved generering av QR-kode + + + + + best name + + + + + best Id + + + + + Back to homepage button + Tilbake til hjemmeside -knapp + + + + Add to contacts + Legg til kontakter + + + + Show invites + + + + + Invites + + + + + + Find a new or existing contact + + + + + Wants to talk to you! + Ønsker å snakke med deg! + + + + Answer incoming call button + Svar innkommende anrop -knapp + + + + Ignore incoming call button + Ignorer innkommende anrop -knapp + + + + Answer + Svar + + + + Ignore + Ignorer + + + + Cancel outgoing call + Avbryt utgående anrop + + + + Cancel + Avbryt + + + + Start video call + + + + + Start audio call + + + + + Clear conversation + + + + + Remove contact + Fjern kontakt + + + + Block contact + Blokker kontakt + + + + Copy number + Kopier nummer + + + + Search your received invitations + + + + + Contact me on Jami + + + + + My Id is : + + + + + %1 + %1 is the contact username + %1 + + + + %1 + %1 is the contact unique identifier + %1 + + + + Call incoming from %1 + Innkommende anrop fra %1 + + + + DeleteAccountDialog + + + Account deletion + + + + + Do you really want to delete the following account? + + + + + If this account hasn't been exported, or added to another device, it will be irrevocably lost. + + + + + Permanently delete account + + + + + Delete + Slett + + + + Cancel account deletion + + + + + Cancel + Avbryt + + + + DeviceItemWidget + + + Form + Skjema + + + + Device Id + + + + + this device + denne enheten + + + + InviteButtonsWidget + + + Accept + Aksepter + + + + Refuse + Avslå + + + + Block + Blokker + + + + LinkDeviceDialog + + + Dialog + Dialogvindu + + + + Enter your account password + + + + + Password + Passord + + + + Ok + OK + + + + Cancel + Avbryt + + + + Exporting account + Eksporterer konto + + + + Your PIN is + + + + + PIN + PIN + + + + This pin and the account password should be entered in your device within 10 minutes. + + + + + Close + Lukk + + + + Link Another Device + + + + + Incorrect password + Feil passord + + + + Something went wrong. +Please try again later. + + + + + MainWindow + + + Settings + Innstillinger + + + + Exit + Avslutt + + + + About + Om + + + + Jami + + + + + NameRegistrationDialog + + + Set Registered Name + + + + + Enter your account password + + + + + Password text input + Passordstekstinndata + + + + Password text entry + Passordteksinnskriving + + + + Password + Passord + + + + Register + Registrer + + + + Cancel + Avbryt + + + + Registering Name + + + + + Something went wrong + + + + + Close + Lukk + + + + Incorrect password + Feil passord + + + + Network error + Nettverksfeil + + + + NewWizardWidget + + + Form + Skjema + + + + Welcome Label + Velkomstetikett + + + + Welcome to + Velkommen til + + + + Welcome Logo + Velkomstlogo + + + + Create Jami account button + + + + + Push button for Jami account creation start trigger + + + + + Create a Jami account + Opprett en Jami-konto + + + + Link device button + Lenk enhet -knapp + + + + Push button for device linkage start trigger + Trykknapp for start av enhetslinking -utløser + + + + Link this device to an account + Lenk denne enheten til en konto + + + + Create Jami SIP account button + + + + + Push button for Jami SIP account creation start trigger + + + + + Create a SIP account + + + + + Link this device to an existing account + Lenk denne enheten til en eksisterende konto + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Ubuntu'; font-size:14px; color:#555555;">To link this device to another account, you first </span><span style=" font-family:'Ubuntu'; font-size:14px; font-weight:600; color:#555555;">need to obtain a PIN</span><span style=" font-family:'Ubuntu'; font-size:14px; color:#555555;"> code. To generate the PIN code:</span></p> +<ol style="margin-top: 0px; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; -qt-list-indent: 1;"><li style=" font-family:'Ubuntu'; font-size:14px; color:#555555;" style=" margin-top:12px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:14px;">Go to the </span><span style=" font-size:14px; font-weight:600;">Account management setting</span><span style=" font-size:14px;"> of a previous device</span></li> +<li style=" font-family:'Ubuntu'; font-size:14px; color:#555555;" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:14px;">Choose the </span><span style=" font-size:14px; font-weight:600;">Jami account</span><span style=" font-size:14px;"> you want to use</span></li> +<li style=" font-family:'Ubuntu'; font-size:14px; color:#555555;" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:14px;">Go to the </span><span style=" font-size:14px; font-weight:600;">Devices</span><span style=" font-size:14px;"> tab</span></li> +<li style=" font-family:'Ubuntu'; font-size:14px; color:#555555;" style=" margin-top:0px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:14px;">Select </span><span style=" font-size:14px; font-weight:600;">Add a device</span></li></ol> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Ubuntu'; font-size:14px; color:#555555;">You will get the necessary PIN to complete this form. The PIN is only valid for </span><span style=" font-family:'Ubuntu'; font-size:14px; font-weight:600; color:#555555;">10 minutes</span><span style=" font-family:'Ubuntu'; font-size:10px; color:#555555;">.</span></p></body></html> + + + + + Enter your pin: + Skriv inn din PIN: + + + + Or import a file: + Eller importer fil: + + + + Link from exported account archive file + Lenk fra eksportert kontoarkivfil + + + + + + (None) + + + + + Password: + Passord: + + + + + Profile + Profil + + + + + Profile name + + + + + Account + Konto + + + + Register your username. +This will reserve the username so that only you can use it. +Your friends will be able to call you with your usename +instead of using your ID. + + + + + Public username checkbox + Offentlig brukernavn -avkryssningsboks + + + + Checkbox selecting if the user wants a public username + Avkryssningsboks som velger hvorvidt en bruker ønsker et offentlig brukernavn + + + + Register public username + Registrer offentlig brukernavn + + + + Public username edit + Redigering av offentlig brukernavn + + + + Choose your username + Velg ditt brukernavn + + + + Password text input + Passordstekstinndata + + + + Password text entry + Passordteksinnskriving + + + + + Password + Passord + + + + + Password confirmation text input + Passordsbekreftelsestekst-inndata + + + + Confirm password + Bekreft passord + + + + SIP Account + SIP-konto + + + + SIP Server edit + + + + + Server + + + + + SIP proxy input + + + + + SIP proxy text entry + + + + + Proxy + Mellomtjener + + + + SIP username input + SIP-brukernavn -inndata + + + + SIP Password text entry + + + + + Username + Brukernavn + + + + + SIP Password text input + + + + + Generating your Jami account… + Oppretter Jami-kontoen din + + + + Previous page button + Forrige side -knapp + + + + push button to access previous page of wizard + trykkbar knapp for å nå forrige side av veivisning + + + + Previous + Forrige + + + + Cancel account create/link + + + + + push button to cancel account creation or linking + + + + + Back + Tilbake + + + + Next page Button + Neste side -knapp + + + + Push button to access next page of wizard + Trykk på knappen for å komme til neste side i veivisningen + + + + Next + Neste + + + + Open File + Åpne fil + + + + Jami archive files (*.gz); All files (*) + + + + + Your account needs to be migrated. Enter your password. + Kontoen din må flyttes. Skriv inn passordet ditt. + + + + Migrating your Jami account... + + + + + Importing account archive... + Importerer kontoarkiv… + + + + Generating your Jami account... + + + + + Generating your SIP account... + + + + + Error creating account + + + + + PasswordDialog + + + Change Account Password + + + + + Enter Current Password + + + + + Enter New Password + + + + + Confirm New Password + + + + + Confirm + + + + + Cancel + Avbryt + + + + Current Password Incorrect + + + + + PhotoBoothDialog + + + Photobooth + Fotoboks + + + + PhotoboothWidget + + + Form + Skjema + + + + Photobooth display + Fotoboksvisning + + + + Choose File + Velg fil + + + + Image Files (*.jpg *.jpeg *.png) + + + + + PrivateBridging + + + Choose File + Velg fil + + + + Files (*) + Filer (*) + + + + QObject + + + No default mail client found + Fant ingen forvalgt e-postklient + + + + + Edit Device Name + + + + + Unlink Device From Account + + + + + Save new device name + + + + + Add as contact + + + + + RingButton + + + Select folder + Velg mappe + + + + SettingsWidget + + + Form + Skjema + + + + Settings + Innstillinger + + + + Account + Konto + + + + + General + Generell + + + + + Audio / Video + + + + + System + System + + + + Enable desktop notifications + + + + + Keep minimized on close + Behold minimert ved lukking + + + + Download folder + Nedlastingsmappe + + + + Save in + Lagre i + + + + Always Recording + + + + + Updates + + + + + Check for updates automatically every + + + + + Interval between update checks in days selector + Intervall mellom oppdateringssjekker i dager -velger + + + + days + + + + + Check for updates now button + Se etter oppdateringer nå -knapp + + + + Check for updates now + Se etter oppdateringer nå + + + + Password + Passord + + + + + Enable + Aktivèr + + + + toggle enable notifications + + + + + Toggle keep minimized on close + + + + + Call Recordings + + + + + Toggle automatic updates + + + + + Jami Account + + + + + + Profile + Profil + + + + + Identity + Identitet + + + + Id + ID + + + + Registered name + Registrert navn + + + + Type here to register a username + + + + + Register + Registrer + + + + Change Password + + + + + Export Account + Eksporter konto + + + + + Delete Account + + + + + Linked Devices + + + + + Link Another Device + + + + + Banned Contacts + Bannlyste kontakter + + + + Format + + + + + Video device framerate selector + + + + + Preview unavailable + + + + + + Advanced Account Settings + + + + + SIP Account + SIP-konto + + + + Username + Brukernavn + + + + Hostname + Vertsnavn + + + + Proxy + Mellomtjener + + + + Audio + Lyd + + + + Microphone + + + + + Audio input device selector + Lydinndataenhets-velger + + + + Output Device + Utgangsenhet + + + + Choose the output device + + + + + Video + Video + + + + Device + Enhet + + + + Video device selector + Videoenhetsvelger + + + + A registered name should not have any spaces and must be at least three letters long + + + + + This name is already taken + + + + + + Enter an alias + + + + + Register this name + + + + + Remove Device + + + + + Enter this account's password to confirm the removal of this device + + + + + Are you sure you wish to remove this device? + + + + + Export Account Here + + + + + Select A Folder For Your Downloads + + + + + Select A Folder For Your Recordings + + + + + VideoOverlay + + + Call on Hold + Samtale på vent + + + + Hold / Unhold + Parker / gjenoppta parkering + + + + Chat + Sludre + + + + Mute Mic + Demp mikrofon + + + + Record call + Ta opp samtale + + + + Name label + Navneetikett + + + + Time elapsed + Forløpt tid + + + + 00:00 + 00:00 + + + + Hangup + Legg på + + + + Mute Video + Demp video + + + + VideoView + + + Share entire screen + Del hele skjermen + + + + Share screen area + Del skjermområde + + + + Share file + Del fil + + + \ No newline at end of file diff --git a/translations/ring_client_windows_nb_NO.ts b/translations/ring_client_windows_nb_NO.ts new file mode 100644 index 00000000..d491fec8 --- /dev/null +++ b/translations/ring_client_windows_nb_NO.ts @@ -0,0 +1,2073 @@ + + + AboutDialog + + + + About + + + + + about button + + + + + credits button + + + + + Credits + + + + + Live Free or Die + + + + + The Microsoft Windows client for Jami. +Jami is a secured and distributed communication software. + + + + + version + + + + + Created by: + + + + + Artwork by: + + + + + Based on the SFLPhone project + + + + + AccountDetails + + + Settings + Innstillinger + + + + General + + + + + Account + + + + + Type + + + + + Parameters + + + + + Hostname + + + + + Public registered username + + + + + + Username + + + + + + Password + Passord… + + + + Proxy + + + + + Voicemail number + + + + + Auto-answer calls + + + + + UPnP enabled + + + + + Account Settings + + + + + Allow Call From Unknown + + + + + Allow Call From Contact + + + + + Allow Call From History + + + + + General account info configuration + + + + + Displayed name + + + + + Displayed alias input + + + + + Hostname URL for DHT bootstrap or SIP + + + + + Public username + + + + + Register username on blockchain button + + + + + Register on blockchain + + + + + Name service URL + + + + + Nameservice URL input + + + + + SIP username input + + + + + SIP password input + + + + + SIP proxy URL input + + + + + SIP voicemail number + + + + + Autoanswer call checkbox + + + + + UPnP enabled checkbox + + + + + Old password input line + + + + + Input old password + + + + + Old Password + + + + + New password text input + + + + + Input new password + + + + + New password + + + + + Password confirmation text input + + + + + Input confirmation + + + + + New pass confirmation + + + + + Change password + + + + + Ok + + + + + Cancel password change button + + + + + Changing password ... + + + + + Allow call from unknown checkbox + + + + + Allow Call From History checkbox + + + + + Allow Call From Contact checkbox + + + + + Ringtone Selection + + + + + Play ringtone button + + + + + Play + + + + + ringtone file selector + + + + + Audio/Video + + + + + Audio/video codecs preferences configuration + + + + + Audio codecs + + + + + Video codecs + + + + + Advanced + + + + + Account advanced configuration + + + + + Registration + + + + + Registration expire timeout (seconds): + + + + + Registration timeout selector spinbox + + + + + Network Interface + + + + + Local Port: + + + + + local port selector spinbox + + + + + same as local radio button + + + + + Same as local parameters + + + + + personalise address and ports radio button + + + + + Set published address and port: + + + + + Address + + + + + ip address text input + + + + + Port + + + + + port selector spinbox + + + + + use STUN checkbox + + + + + Use STUN + + + + + + Server URL + + + + + use TURN checkbox + + + + + Use TURN + + + + + TURN server URL input + + + + + TURN server username input + + + + + TURN server password input + + + + + TURN server Realm input + + + + + Realm + + + + + SDP Session Negotiation (ICE Fallback) + + + + + These settings are only used during SDP session negotiation in case ICE is not supported by the server or peer. + + + + + Audio RTP Port Range + + + + + + Min + + + + + + Lower boundary for audio RTP port range selector + + + + + + Max + + + + + + higher boundary for audio RTP port range selector + + + + + Video RTP Port Range + + + + + Security + + + + + Account security configuration + + + + + Certificate authaurity certificate selector + + + + + User certificate selector + + + + + private key password input + + + + + User private key selector + + + + + Encrypt media stream (SRTP) checkbox + + + + + Media Stream Encryption (SRTP) + + + + + use default ciphers checkbox + + + + + Devices + + + + + Account devices management + + + + + Add device button + + + + + Add device + + + + + Export on the network + + + + + Password text input + + + + + Password (required) + + + + + Cancel account export for linking button + + + + + + Cancel + Avbryt + + + + To add a new device to your Jami account, you export your account on the network. This will generate a pin that must be entered on your new device within 5 minutes of its generation. + + + + + Validate export on DHT for device linking button + + + + + Your generated pin: + + + + + Generated PIN for linking + + + + + PIN + + + + + This pin should be entered on your new device within 5 minutes. You may generate a new one at any moment. + + + + + Accept PIN generation and quit button + + + + + OK + OK + + + + Banned Contacts + + + + + Account banned contacts management tab + + + + + Published Address + + + + + CA certificate + + + + + User certificate + + + + + Private key + + + + + Private key password + + + + + Use default ciphers + + + + + AccountItemDelegate + + + Add Account + + + + + AdvancedSettingsWidget + + + Form + + + + + Call Settings + + + + + Allow Calls From Untrusted Peers + + + + + Auto Answer Calls + + + + + Enable Custom Ringtone + + + + + + Add a custom ringtone + + + + + Name Server + + + + + Address + + + + + OpenDHT Configuration + + + + + Enable Proxy + + + + + Bootstrap + + + + + Security + + + + + Private Key Password + + + + + User Certificate + + + + + no password + + + + + Private Key + + + + + CA Certificate + + + + + Connectivity + + + + + TURN Address + + + + + Use STUN + + + + + STUN Address + + + + + TURN Username + + + + + TURN Password + + + + + Use UPnP + + + + + Use TURN + + + + + Audio Codecs + + + + + Video Codecs + + + + + Audio Files (*.wav *.ogg *.opus *.mp3 *aiff *wma) + + + + + AnimatedOverlay + + + Form + + + + + BannedContactsWidget + + + Form + + + + + Banned contacts list + + + + + Banned ID + + + + + Deban contact button + + + + + Deban contact, and add to contact list + + + + + CallWidget + + + Show conversations + + + + + Conversations + + + + + Search contact text input + + + + + Jami is free software for universal communication which respects the freedoms and privacy of its users. + Jami er fri programvare til universell kommunikasjon som respekterer brukernes frihet og rett til privatliv. + + + + + This is your ID. +Copy and share it with your friends! + + + + + + Show ring ID QR code + + + + + Share ring ID button + + + + + Double-click to copy + + + + + Error while generating QR Code + + + + + + best name + + + + + best Id + + + + + Back to homepage button + + + + + Add to contacts + + + + + Show invites + + + + + Invites + + + + + + Find a new or existing contact + + + + + Wants to talk to you! + + + + + Answer incoming call button + + + + + Ignore incoming call button + + + + + Answer + + + + + Ignore + + + + + Cancel outgoing call + + + + + Cancel + Avbryt + + + + Start video call + + + + + Start audio call + + + + + Clear conversation + + + + + Remove contact + + + + + Block contact + + + + + Copy number + + + + + Search your received invitations + + + + + Contact me on Jami + + + + + My Id is : + + + + + Message incoming from %1 + + + + + %1 + %1 is the contact username + + + + + %1 + %1 is the contact unique identifier + + + + + Call incoming from %1 + + + + + ContactDialog + + + Dialog + + + + + New Contact + + + + + Enter a name... + + + + + DeleteAccountDialog + + + Account deletion + + + + + Do you really want to delete the following account? + + + + + If this account hasn't been exported, or added to another device, it will be irrevocably lost. + + + + + Permanently delete account + + + + + Delete + + + + + Cancel account deletion + + + + + Cancel + Avbryt + + + + Form + + + Form + + + + + PushButton + + + + + InviteButtonsWidget + + + Accept + + + + + Refuse + + + + + Block + + + + + LinkDevWidget + + + Form + + + + + Add A New Device + + + + + To add a new device, enter your account password: + + + + + Cancel + Avbryt + + + + Enter + + + + + Exporting account on the network + + + + + Your generated pin: + + + + + This pin and the account password should be entered in your device within 5 minutes. + + + + + Close + + + + + Your account password was incorrect + + + + + Something went wrong. +Please try again later. + + + + + MainWindow + + + Settings + Innstillinger + + + + Exit + + + + + About + + + + + Jami + + + + + NewWizardWidget + + + Form + + + + + Welcome Label + + + + + Welcome to + + + + + Welcome Logo + + + + + Create Jami account button + + + + + Push button for Jami account creation start trigger + + + + + Create a Jami account + + + + + Link device button + + + + + Push button for device linkage start trigger + + + + + Link this device to an account + + + + + Link this device to an existing account + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Ubuntu'; font-size:14px; color:#555555;">To link this device to another account, you first </span><span style=" font-family:'Ubuntu'; font-size:14px; font-weight:600; color:#555555;">need to obtain a PIN</span><span style=" font-family:'Ubuntu'; font-size:14px; color:#555555;"> code. To generate the PIN code:</span></p> +<ol style="margin-top: 0px; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; -qt-list-indent: 1;"><li style=" font-family:'Ubuntu'; font-size:14px; color:#555555;" style=" margin-top:12px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:14px;">Go to the </span><span style=" font-size:14px; font-weight:600;">Account management setting</span><span style=" font-size:14px;"> of a previous device</span></li> +<li style=" font-family:'Ubuntu'; font-size:14px; color:#555555;" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:14px;">Choose the </span><span style=" font-size:14px; font-weight:600;">Jami account</span><span style=" font-size:14px;"> you want to use</span></li> +<li style=" font-family:'Ubuntu'; font-size:14px; color:#555555;" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:14px;">Go to the </span><span style=" font-size:14px; font-weight:600;">Devices</span><span style=" font-size:14px;"> tab</span></li> +<li style=" font-family:'Ubuntu'; font-size:14px; color:#555555;" style=" margin-top:0px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:14px;">Select </span><span style=" font-size:14px; font-weight:600;">Add a device</span></li></ol> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Ubuntu'; font-size:14px; color:#555555;">You will get the necessary PIN to complete this form. The PIN is only valid for </span><span style=" font-family:'Ubuntu'; font-size:14px; font-weight:600; color:#555555;">10 minutes</span><span style=" font-family:'Ubuntu'; font-size:10px; color:#555555;">.</span></p></body></html> + + + + + Enter your pin: + + + + + Or import a file: + + + + + Link from exported account archive file + + + + + + + (None) + + + + + Password: + + + + + Profile + + + + + Profile name + + + + + Account + + + + + Register your username. +This will reserve the username so that only you can use it. +Your friends will be able to call you with your usename +instead of using your ID. + + + + + Public username checkbox + + + + + Checkbox selecting if the user wants a public username + + + + + Register public username + + + + + Public username edit + + + + + Choose your username + + + + + Password text input + + + + + Password text entry + + + + + Password + Passord… + + + + + Password confirmation text input + + + + + Confirm password + + + + + Generating your Jami account… + + + + + Previous page button + + + + + push button to access previous page of wizard + + + + + Previous + + + + + Cancel account create/link + + + + + push button to cancel account creation or linking + + + + + Back + + + + + Next page Button + + + + + Push button to access next page of wizard + + + + + Next + + + + + Open File + + + + + Jami archive files (*.gz); All files (*) + + + + + Your account needs to be migrated. Enter your password. + + + + + Migrating your Jami account... + + + + + Importing account archive... + + + + + Generating your Jami account... + + + + + Error creating account + + + + + PasswordDialog + + + Change Account Password + + + + + Enter Current Password + + + + + Enter New Password + + + + + Confirm New Password + + + + + Confirm + + + + + Cancel + Avbryt + + + + Password Changed Successfully + + + + + Current Password Incorrect + + + + + PhotoBoothDialog + + + Photobooth + + + + + PhotoboothWidget + + + Form + + + + + Photobooth display + + + + + Choose File + + + + + Image Files (*.jpg *.jpeg *.png) + + + + + PrivateBridging + + + Choose File + + + + + Files (*) + + + + + QObject + + + No default mail client found + + + + + Edit Device Name + + + + + Unlink Device From Account + + + + + Unblock Contact + + + + + Jami account + Default alias for new Jami account + + + + + RegNameDialog + + + Set Registered Name + + + + + Are you sure you would like to register this name? + + + + + Once associated to this account, it cannot be changed. + + + + + Your new registered name would be: + + + + + Confirm Registration + + + + + Cancel + Avbryt + + + + The name has been successfully registered! + + + + + Something went wrong. + + + + + Please try again later + + + + + Your account does not have a registered name + + + + + RingButton + + + Select folder + + + + + SetAvatarDialog + + + Change Your Avatar Image + + + + + Save + + + + + Take Picture + + + + + Camera + + + + + Select A File + + + + + Cancel + Avbryt + + + + Open Image + + + + + Image Files (*.jpg *.jpeg *.png *.bmp) + + + + + SettingsWidget + + + Form + + + + + Settings + Innstillinger + + + + + Account + + + + + General + + + + + Audio / Video + + + + + System + + + + + enable notifications checkbox + + + + + Enable desktop notifications + + + + + keep minimized on close checkbox + + + + + Keep minimized on close + + + + + Download folder + + + + + Recordings + + + + + Save in + + + + + Always Recording + + + + + Updates + + + + + Autamatic update checks checkbox + + + + + Check for updates automatically every + + + + + Interval between update checks in days selector + + + + + days + + + + + Check for updates now button + + + + + Check for updates now + + + + + Registered Name + + + + + ID + ID + + + + Password + Passord… + + + + Enable + + + + + Type here to register a username + + + + + Change Password + + + + + Export Account + + + + + Delete Account + + + + + + + Linked Devices + + + + + Link Another Device + + + + + + + Blocked Contacts + + + + + Advanced Account Settings + + + + + Audio + + + + + Microphone + + + + + Audio input device selector + + + + + Output Device + + + + + Choose the output device + + + + + Video + + + + + Device + + + + + Video device selector + + + + + Resolution + + + + + Video device resolution selector + + + + + Preview unavailable during call + + + + + Enter the displayed name + + + + + + A registered name should not have any spaces and must be at least three letters long + + + + + This name is already taken + + + + + This registered name is already taken + + + + + This name is available + + + + + Register this name + + + + + Remove Device + + + + + Enter this account's password to confirm the removal of this device + + + + + Please confirm that you wish to remove this device + + + + + Export Account Here + + + + + Select A Folder For Your Downloads + + + + + Select A Folder For Your Recordings + + + + + VideoOverlay + + + Call on Hold + + + + + Hold / Unhold + + + + + Chat + + + + + Mute Mic + + + + + Record call + + + + + Name label + + + + + Time elapsed + + + + + 00:00 + + + + + Hangup + + + + + Mute Video + + + + + VideoView + + + Share entire screen + + + + + Share screen area + + + + + Share file + + + + \ No newline at end of file diff --git a/translations/ring_client_windows_nl.ts b/translations/ring_client_windows_nl.ts new file mode 100644 index 00000000..147db2a7 --- /dev/null +++ b/translations/ring_client_windows_nl.ts @@ -0,0 +1,1605 @@ + + + AboutDialog + + + + About + Over + + + + about button + over-knop + + + + credits button + knop met dank aan + + + + Credits + Met dank aan + + + + Free as in Freedom + + + + + The Microsoft Windows client for Jami. +Jami is a secured and distributed communication software. + De Microsoft Windows-cliënt voor Jami. +Jami is software voor beveiligde en gedistribueerde communicatie. + + + + version + versie + + + + Created by: + Geschreven door: + + + + Artwork by: + Illustraties door: + + + + Based on the SFLPhone project + Gebaseerd op het SFLPhone-project + + + + AccountItemDelegate + + + Add Account + Account toevoegen + + + + AdvancedSIPSettingsWidget + + + Form + Formulier + + + + Call Settings + Oproepinstellingen + + + + Auto Answer Calls + Oproepen automatisch beantwoorden + + + + Enable Custom Ringtone + Aangepaste beltoon inschakelen + + + + Connectivity + Connectiviteit + + + + STUN Address + STUN-adres + + + + Use STUN + STUN gebruiken + + + + Use UPnP + UPnP gebruiken + + + + Use TURN + TURN gebruiken + + + + TURN Password + TURN-wachtwoord + + + + TURN Username + TURN-gebruikersnaam + + + + TURN Address + TURN-adres + + + + Media + Media + + + + Enable Video + Video inschakelen + + + + Video Codecs + Videocodecs + + + + Audio Codecs + Audiocodecs + + + + Audio Files (*.wav *.ogg *.opus *.mp3 *aiff *wma) + Audiobestanden (*.wav *.ogg *.opus *.mp3 *aiff *wma) + + + + Add a custom ringtone + Voeg een aangepaste beltoon toe + + + + AdvancedSettingsWidget + + + Form + Formulier + + + + Call Settings + Oproepinstellingen + + + + Allow Calls From Untrusted Peers + Oproepen van onvertrouwde gebruikers toestaan + + + + Auto Answer Calls + Oproepen automatisch beantwoorden + + + + Enable Custom Ringtone + Aangepaste beltoon inschakelen + + + + Add a custom ringtone + Voeg een aangepaste beltoon toe + + + + Name Server + Naamserver + + + + Address + Adres + + + + OpenDHT Configuration + OpenDHT-configuratie + + + + Enable Proxy + Proxy inschakelen + + + + Bootstrap + Bootstrap + + + + Security + Beveiliging + + + + Private Key Password + Wachtwoord persoonlijke sleutel + + + + User Certificate + Gebruikerscertificaat + + + + Private Key + Privésleutel + + + + CA Certificate + CA-certificaat + + + + Connectivity + Connectiviteit + + + + Use STUN + STUN gebruiken + + + + STUN Address + STUN-adres + + + + Use UPnP + UPnP gebruiken + + + + Use TURN + TURN gebruiken + + + + TURN Password + TURN-wachtwoord + + + + TURN Username + TURN-gebruikersnaam + + + + TURN Address + TURN-adres + + + + Media + Media + + + + Enable Video + Video inschakelen + + + + Audio Codecs + Audiocodecs + + + + Video Codecs + Videocodecs + + + + Audio Files (*.wav *.ogg *.opus *.mp3 *aiff *wma) + Audiobestanden (*.wav *.ogg *.opus *.mp3 *aiff *wma) + + + + AnimatedOverlay + + + Form + Formulier + + + + BannedItemWidget + + + Form + Formulier + + + + name + naam + + + + id + ID + + + + CallWidget + + + Show conversations + Gesprekken tonen + + + + Conversations + Gesprekken + + + + Search contact text input + Tekstinvoer contact zoeken + + + + Jami is free software for universal communication which respects the freedoms and privacy of its users. + Jami is vrije software voor universele communicatie, die de vrijheden en privacy van haar gebruikers eerbiedigt. + + + + + This is your ID. +Copy and share it with your friends! + + + Dit is uw ID. +Kopieer en deel het met uw vrienden! + + + + Show ring ID QR code + Toon QR-code voor Ring-ID + + + + Share ring ID button + Knop Ring-ID delen + + + + Double-click to copy + Dubbelklik om te kopiëren + + + + Error while generating QR Code + Fout bij het aanmaken van QR-code + + + + + best name + beste naam + + + + best Id + beste ID + + + + Back to homepage button + Knop terug naar startpagina + + + + Add to contacts + Toevoegen aan contacten + + + + Show invites + Uitnodigingen tonen + + + + Invites + Uitnodigingen + + + + + Find a new or existing contact + Zoek een nieuw of bestaand contact + + + + Wants to talk to you! + Wil met u praten! + + + + Answer incoming call button + Knop inkomende oproep beantwoorden + + + + Ignore incoming call button + Knop inkomende oproep negeren + + + + Answer + Beantwoorden + + + + Ignore + Negeren + + + + Cancel outgoing call + Uitgaande oproep annuleren + + + + Cancel + Annuleren + + + + Start video call + Video-oproep starten + + + + Start audio call + Audio-oproep starten + + + + Clear conversation + Gesprek wissen + + + + Remove contact + Contact verwijderen + + + + Block contact + Contact blokkeren + + + + Copy number + Nummer kopiëren + + + + Search your received invitations + Zoek naar uw ontvangen uitnodigingen + + + + Contact me on Jami + Contacteer me op Jami + + + + My Id is : + Mijn ID is: + + + + %1 + %1 is the contact username + %1 + + + + %1 + %1 is the contact unique identifier + %1 + + + + Call incoming from %1 + Inkomende oproep van %1 + + + + DeleteAccountDialog + + + Account deletion + Accountverwijdering + + + + Do you really want to delete the following account? + Weet u zeker dat u het volgende account wilt verwijderen? + + + + If this account hasn't been exported, or added to another device, it will be irrevocably lost. + Als dit account nog niet geëxporteerd is of nog niet toegevoegd is aan een ander apparaat, zal het onherroepelijk verloren gaan + + + + Permanently delete account + Account voorgoed verwijderen + + + + Delete + Verwijderen + + + + Cancel account deletion + Accountverwijdering annuleren + + + + Cancel + Annuleren + + + + DeviceItemWidget + + + Form + Formulier + + + + Device Id + Apparaat-ID + + + + this device + dit apparaat + + + + InviteButtonsWidget + + + Accept + Accepteren + + + + Refuse + Afwijzen + + + + Block + Blokkeren + + + + LinkDeviceDialog + + + Dialog + Dialoog + + + + Enter your account password + Voer uw accountwachtwoord in + + + + Password + Wachtwoord + + + + Ok + Oké + + + + Cancel + Annuleren + + + + Exporting account + Account wordt geëxporteerd + + + + Your PIN is + Uw pincode is + + + + PIN + Pincode + + + + This pin and the account password should be entered in your device within 10 minutes. + Deze pincode en het accountwachtwoord moeten binnen 10 minuten op uw apparaat worden ingevoerd + + + + Close + Sluiten + + + + Link Another Device + Een ander apparaat koppelen + + + + Incorrect password + Verkeerd wachtwoord + + + + Something went wrong. +Please try again later. + Er ging iets mis. +Probeer het later opnieuw. + + + + MainWindow + + + Settings + Instellingen + + + + Exit + Afsluiten + + + + About + Over + + + + Jami + Jami + + + + NameRegistrationDialog + + + Set Registered Name + Stel geregistreerde naam in + + + + Enter your account password + Voer uw accountwachtwoord in + + + + Password text input + Wachtwoordtekstinvoer + + + + Password text entry + Wachtwoordtekstinvoer + + + + Password + Wachtwoord + + + + Register + Registreren + + + + Cancel + Annuleren + + + + Registering Name + Naam wordt geregistreerd + + + + Something went wrong + Er ging iets mis + + + + Close + Sluiten + + + + Incorrect password + Verkeerd wachtwoord + + + + Network error + Netwerkfout + + + + NewWizardWidget + + + Form + Formulier + + + + Welcome Label + Welkomstlabel + + + + Welcome to + Welkom bij + + + + Welcome Logo + Welkomstlogo + + + + Create Jami account button + Knop Jami-account aanmaken + + + + Push button for Jami account creation start trigger + Trekker voor starten van aanmaken van Jami-account na druk op knop + + + + Create a Jami account + Een Jami-account aanmaken + + + + Link device button + Knop apparaat koppelen + + + + Push button for device linkage start trigger + Trekker voor koppelen van apparaat na druk op knop + + + + Link this device to an account + Dit apparaat aan een account koppelen + + + + Create Jami SIP account button + Knop Jami-SIP-account aanmaken + + + + Push button for Jami SIP account creation start trigger + Trekker voor starten van aanmaken van Jami-SIP-account na druk op knop + + + + Create a SIP account + Een SIP-account aanmaken + + + + Link this device to an existing account + Dit apparaat aan een bestaand account koppelen + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Ubuntu'; font-size:14px; color:#555555;">To link this device to another account, you first </span><span style=" font-family:'Ubuntu'; font-size:14px; font-weight:600; color:#555555;">need to obtain a PIN</span><span style=" font-family:'Ubuntu'; font-size:14px; color:#555555;"> code. To generate the PIN code:</span></p> +<ol style="margin-top: 0px; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; -qt-list-indent: 1;"><li style=" font-family:'Ubuntu'; font-size:14px; color:#555555;" style=" margin-top:12px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:14px;">Go to the </span><span style=" font-size:14px; font-weight:600;">Account management setting</span><span style=" font-size:14px;"> of a previous device</span></li> +<li style=" font-family:'Ubuntu'; font-size:14px; color:#555555;" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:14px;">Choose the </span><span style=" font-size:14px; font-weight:600;">Jami account</span><span style=" font-size:14px;"> you want to use</span></li> +<li style=" font-family:'Ubuntu'; font-size:14px; color:#555555;" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:14px;">Go to the </span><span style=" font-size:14px; font-weight:600;">Devices</span><span style=" font-size:14px;"> tab</span></li> +<li style=" font-family:'Ubuntu'; font-size:14px; color:#555555;" style=" margin-top:0px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:14px;">Select </span><span style=" font-size:14px; font-weight:600;">Add a device</span></li></ol> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Ubuntu'; font-size:14px; color:#555555;">You will get the necessary PIN to complete this form. The PIN is only valid for </span><span style=" font-family:'Ubuntu'; font-size:14px; font-weight:600; color:#555555;">10 minutes</span><span style=" font-family:'Ubuntu'; font-size:10px; color:#555555;">.</span></p></body></html> + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Ubuntu'; font-size:14px; color:#555555;">Om dit apparaat aan een ander account te koppelen, dient u eerst </span><span style=" font-family:'Ubuntu'; font-size:14px; font-weight:600; color:#555555;">een pincode te verkrijgen</span><span style=" font-family:'Ubuntu'; font-size:14px; color:#555555;">. Om de pincode te genereren:</span></p> +<ol style="margin-top: 0px; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; -qt-list-indent: 1;"><li style=" font-family:'Ubuntu'; font-size:14px; color:#555555;" style=" margin-top:12px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:14px;">Ga naar de </span><span style=" font-size:14px; font-weight:600;">Accountbeheerinstellingen</span><span style=" font-size:14px;"> van een vorig apparaat</span></li> +<li style=" font-family:'Ubuntu'; font-size:14px; color:#555555;" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:14px;">Kies het </span><span style=" font-size:14px; font-weight:600;">Jami-account</span><span style=" font-size:14px;"> dat u wilt gebruiken</span></li> +<li style=" font-family:'Ubuntu'; font-size:14px; color:#555555;" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:14px;">Ga naar het tabblad </span><span style=" font-size:14px; font-weight:600;">Apparaten</span><span style=" font-size:14px;"></span></li> +<li style=" font-family:'Ubuntu'; font-size:14px; color:#555555;" style=" margin-top:0px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:14px;">Selecteer </span><span style=" font-size:14px; font-weight:600;">Een apparaat toevoegen</span></li></ol> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Ubuntu'; font-size:14px; color:#555555;">U zult de pincode krijgen die u nodig heeft om dit proces te voltooien. De pincode is slechts </span><span style=" font-family:'Ubuntu'; font-size:14px; font-weight:600; color:#555555;">10 minuten</span><span style=" font-family:'Ubuntu'; font-size:10px; color:#555555;"> geldig.</span></p></body></html> + + + + Enter your pin: + Voer uw pincode in: + + + + Or import a file: + Of importeer een bestand: + + + + Link from exported account archive file + Koppelen van geëxporteerd accountarchiefbestand + + + + + + (None) + (geen) + + + + Password: + Wachtwoord: + + + + + Profile + Profiel + + + + + Profile name + Profielnaam + + + + Account + Account + + + + Register your username. +This will reserve the username so that only you can use it. +Your friends will be able to call you with your usename +instead of using your ID. + Registreer uw gebruikersnaam. +Dit zal de gebruikersnaam registreren, zodat enkel u ze kunt gebruiken. +Uw vrienden zullen u kunnen bellen met uw gebruikersnaam +in plaats van uw Ring-ID. + + + + Public username checkbox + Selectievakje openbare gebruikersnaam + + + + Checkbox selecting if the user wants a public username + Selectievakje om te kiezen of de gebruiker een openbare gebruikersnaam wil + + + + Register public username + Registreer een openbare gebruikersnaam + + + + Public username edit + Bewerken openbare gebruikersnaam + + + + Choose your username + Kies uw gebruikersnaam + + + + Password text input + Wachtwoordtekstinvoer + + + + Password text entry + Wachtwoordtekstinvoer + + + + + Password + Wachtwoord + + + + + Password confirmation text input + Wachtwoordbevestigingstekstinvoer + + + + Confirm password + Bevestig wachtwoord + + + + SIP Account + SIP-account + + + + SIP Server edit + SIP-server bewerken + + + + Server + Server + + + + SIP proxy input + SIP-proxy-invoer + + + + SIP proxy text entry + SIP-proxy-tekstinvoer + + + + Proxy + Proxy + + + + SIP username input + SIP-gebruikersnaaminvoer + + + + SIP Password text entry + SIP-wachtwoord-tekstinvoer + + + + Username + Gebruikersnaam + + + + + SIP Password text input + SIP-wachtwoord-tekstinvoer + + + + Generating your Jami account… + Uw Jami-account wordt aangemaakt… + + + + Previous page button + Knop vorige pagina + + + + push button to access previous page of wizard + druk op de knop om naar de vorige pagina van de assistent te gaan + + + + Previous + Vorige + + + + Cancel account create/link + Aanmaken/koppelen van account annuleren + + + + push button to cancel account creation or linking + trekker voor annuleren van aanmaken of verwijderen van account + + + + Back + Terug + + + + Next page Button + Knop volgende pagina + + + + Push button to access next page of wizard + Druk op de knop om naar de volgende pagina van de assistent te gaan + + + + Next + Volgende + + + + Open File + Bestand openen + + + + Jami archive files (*.gz); All files (*) + Jami-archiefbestanden (*.gz); Alle bestanden (*) + + + + Your account needs to be migrated. Enter your password. + Uw account moet gemigreerd worden. Voer uw wachtwoord in. + + + + Migrating your Jami account... + Uw Jami-account wordt gemigreerd… + + + + Importing account archive... + Accountarchief importeren… + + + + Generating your Jami account... + Uw Jami-account wordt aangemaakt… + + + + Generating your SIP account... + Uw SIP-account wordt gegenereerd… + + + + Error creating account + Fout bij aanmaken van account + + + + PasswordDialog + + + Change Account Password + Accountwachtwoord wijzigen + + + + Enter Current Password + Voer huidig wachtwoord in + + + + Enter New Password + Voer nieuw wachtwoord in + + + + Confirm New Password + Bevestig nieuw wachtwoord + + + + Confirm + Bevestigen + + + + Cancel + Annuleren + + + + Current Password Incorrect + Huidige wachtwoord is verkeerd + + + + PhotoBoothDialog + + + Photobooth + Fotoautomaat + + + + PhotoboothWidget + + + Form + Formulier + + + + Photobooth display + Fotoautomaatweergave + + + + Choose File + Bestand kiezen + + + + Image Files (*.jpg *.jpeg *.png) + Afbeeldingsbestanden (*.jpg *.jpeg *.png) + + + + PrivateBridging + + + Choose File + Bestand kiezen + + + + Files (*) + Bestanden (*) + + + + QObject + + + No default mail client found + Geen standaard-e-mailprogramma gevonden + + + + + Edit Device Name + Apparaatnaam bewerken + + + + Unlink Device From Account + Apparaat ontkoppelen van account + + + + Save new device name + Nieuwe apparaatnaam opslaan + + + + Add as contact + Toevoegen aan contacten + + + + RingButton + + + Select folder + Kies een map + + + + SettingsWidget + + + Form + Formulier + + + + Settings + Instellingen + + + + Account + Account + + + + + General + Algemeen + + + + + Audio / Video + Audio/video + + + + System + Systeem + + + + Enable desktop notifications + Bureaubladmeldingen inschakelen + + + + Keep minimized on close + Minimaliseren bij sluiten + + + + Download folder + Downloadmap + + + + Save in + Opslaan in + + + + Always Recording + Altijd opnemen + + + + Updates + Updates + + + + Check for updates automatically every + Automatisch controleren op updates elke + + + + Interval between update checks in days selector + Selectie interval in dagen tussen controles op updates + + + + days + dagen + + + + Check for updates now button + Knop nu controleren op updates + + + + Check for updates now + Nu controleren op updates + + + + Password + Wachtwoord + + + + + Enable + Inschakelen + + + + toggle enable notifications + schakelaar meldingen inschakelen + + + + Toggle keep minimized on close + Schakelaar minimaliseren bij sluiten + + + + Call Recordings + Oproepopnamen + + + + Toggle automatic updates + Schakelaar automatische updates + + + + Jami Account + Jami-account + + + + + Profile + Profiel + + + + + Identity + Identiteit + + + + Id + ID + + + + Registered name + Geregistreerde naam + + + + Type here to register a username + Typ hier om een gebruikersnaam te registreren + + + + Register + Registreren + + + + Change Password + Wachtwoord wijzigen + + + + Export Account + Account exporteren + + + + + Delete Account + Account verwijderen + + + + Linked Devices + Gekoppelde apparaten + + + + Link Another Device + Een ander apparaat koppelen + + + + Banned Contacts + Geblokkeerde contacten + + + + Format + Formaat + + + + Video device framerate selector + Framerateselectie voor video-apparaat + + + + Preview unavailable + Voorbeeld niet beschikbaar + + + + + Advanced Account Settings + Geavanceerde accountinstellingen + + + + SIP Account + SIP-account + + + + Username + Gebruikersnaam + + + + Hostname + Hostnaam + + + + Proxy + Proxy + + + + Audio + Geluid + + + + Microphone + Microfoon + + + + Audio input device selector + Selectie audio-invoerapparaat + + + + Output Device + Uitvoerapparaat + + + + Choose the output device + Kies het uitvoerapparaat + + + + Video + Video + + + + Device + Apparaat + + + + Video device selector + Selectie video-apparaat + + + + A registered name should not have any spaces and must be at least three letters long + Een geregistreerde naam mag geen spaties bevatten, en moet minstens drie tekens lang zijn + + + + This name is already taken + Deze naam is reeds in gebruik + + + + + Enter an alias + Voer een alias in + + + + Register this name + Deze naam registreren + + + + Remove Device + Apparaat verwijderen + + + + Enter this account's password to confirm the removal of this device + Voer het wachtwoord van dit account in om het verwijderen van dit apparaat te bevestigen + + + + Are you sure you wish to remove this device? + Weet u zeker dat u dit apparaat wilt verwijderen? + + + + Export Account Here + Account hier exporteren + + + + Select A Folder For Your Downloads + Selecteer een map voor uw downloads + + + + Select A Folder For Your Recordings + Kies een map voor uw opnamen + + + + VideoOverlay + + + Call on Hold + Telefoongesprek in wacht + + + + Hold / Unhold + In wacht zetten / uit wacht halen + + + + Chat + Chat + + + + Mute Mic + Microfoon dempen + + + + Record call + Gesprek opnemen + + + + Name label + Naamlabel + + + + Time elapsed + Tijd verstreken + + + + 00:00 + 00:00 + + + + Hangup + Ophangen + + + + Mute Video + Video uitschakelen + + + + VideoView + + + Share entire screen + Scherm delen + + + + Share screen area + Schermgebied delen + + + + Share file + Bestand delen + + + \ No newline at end of file diff --git a/translations/ring_client_windows_nl_BE.ts b/translations/ring_client_windows_nl_BE.ts new file mode 100644 index 00000000..b78da348 --- /dev/null +++ b/translations/ring_client_windows_nl_BE.ts @@ -0,0 +1,1605 @@ + + + AboutDialog + + + + About + Over + + + + about button + over-knop + + + + credits button + knop met dank aan + + + + Credits + Met dank aan + + + + Free as in Freedom + + + + + The Microsoft Windows client for Jami. +Jami is a secured and distributed communication software. + De Microsoft Windows-cliënt voor Jami. +Jami is software voor beveiligde en gedistribueerde communicatie. + + + + version + versie + + + + Created by: + Geschreven door: + + + + Artwork by: + Illustraties door: + + + + Based on the SFLPhone project + Gebaseerd op het SFLPhone-project + + + + AccountItemDelegate + + + Add Account + Account toevoegen + + + + AdvancedSIPSettingsWidget + + + Form + Formulier + + + + Call Settings + Oproepinstellingen + + + + Auto Answer Calls + Oproepen automatisch beantwoorden + + + + Enable Custom Ringtone + Aangepaste beltoon inschakelen + + + + Connectivity + Connectiviteit + + + + STUN Address + STUN-adres + + + + Use STUN + STUN gebruiken + + + + Use UPnP + UPnP gebruiken + + + + Use TURN + TURN gebruiken + + + + TURN Password + TURN-paswoord + + + + TURN Username + TURN-gebruikersnaam + + + + TURN Address + TURN-adres + + + + Media + Media + + + + Enable Video + Video inschakelen + + + + Video Codecs + Videocodecs + + + + Audio Codecs + Audiocodecs + + + + Audio Files (*.wav *.ogg *.opus *.mp3 *aiff *wma) + Audiobestanden (*.wav *.ogg *.opus *.mp3 *aiff *wma) + + + + Add a custom ringtone + Voeg een aangepaste beltoon toe + + + + AdvancedSettingsWidget + + + Form + Formulier + + + + Call Settings + Oproepinstellingen + + + + Allow Calls From Untrusted Peers + Oproepen van onvertrouwde gebruikers toestaan + + + + Auto Answer Calls + Oproepen automatisch beantwoorden + + + + Enable Custom Ringtone + Aangepaste beltoon inschakelen + + + + Add a custom ringtone + Voeg een aangepaste beltoon toe + + + + Name Server + Naamserver + + + + Address + Adres + + + + OpenDHT Configuration + OpenDHT-configuratie + + + + Enable Proxy + Proxy inschakelen + + + + Bootstrap + Bootstrap + + + + Security + Beveiliging + + + + Private Key Password + Paswoord persoonlijke sleutel + + + + User Certificate + Gebruikerscertificaat + + + + Private Key + Privésleutel + + + + CA Certificate + CA-certificaat + + + + Connectivity + Connectiviteit + + + + Use STUN + STUN gebruiken + + + + STUN Address + STUN-adres + + + + Use UPnP + UPnP gebruiken + + + + Use TURN + TURN gebruiken + + + + TURN Password + TURN-paswoord + + + + TURN Username + TURN-gebruikersnaam + + + + TURN Address + TURN-adres + + + + Media + Media + + + + Enable Video + Video inschakelen + + + + Audio Codecs + Audiocodecs + + + + Video Codecs + Videocodecs + + + + Audio Files (*.wav *.ogg *.opus *.mp3 *aiff *wma) + Audiobestanden (*.wav *.ogg *.opus *.mp3 *aiff *wma) + + + + AnimatedOverlay + + + Form + Formulier + + + + BannedItemWidget + + + Form + Formulier + + + + name + naam + + + + id + ID + + + + CallWidget + + + Show conversations + Gesprekken tonen + + + + Conversations + Gesprekken + + + + Search contact text input + Tekstingave contact zoeken + + + + Jami is free software for universal communication which respects the freedoms and privacy of its users. + Jami is vrije software voor universele communicatie, die de vrijheden en privacy van zijn gebruikers eerbiedigt. + + + + + This is your ID. +Copy and share it with your friends! + + + Dit is uw ID. +Kopieer en deel hem met uw vrienden! + + + + Show ring ID QR code + Toon QR-code voor Ring-ID + + + + Share ring ID button + Knop Ring-ID delen + + + + Double-click to copy + Dubbelklik om te kopiëren + + + + Error while generating QR Code + Fout bij het aanmaken van QR-code + + + + + best name + beste naam + + + + best Id + beste ID + + + + Back to homepage button + Knop terug naar startblad + + + + Add to contacts + Toevoegen aan contacten + + + + Show invites + Uitnodigingen tonen + + + + Invites + Uitnodigingen + + + + + Find a new or existing contact + Zoek een nieuw of bestaand contact + + + + Wants to talk to you! + Wilt met u praten! + + + + Answer incoming call button + Knop inkomende oproep beantwoorden + + + + Ignore incoming call button + Knop inkomende oproep negeren + + + + Answer + Beantwoorden + + + + Ignore + Negeren + + + + Cancel outgoing call + Uitgaande oproep annuleren + + + + Cancel + Annuleren + + + + Start video call + Video-oproep starten + + + + Start audio call + Audio-oproep starten + + + + Clear conversation + Gesprek wissen + + + + Remove contact + Contact verwijderen + + + + Block contact + Contact blokkeren + + + + Copy number + Nummer kopiëren + + + + Search your received invitations + Zoek naar uw ontvangen uitnodigingen + + + + Contact me on Jami + Contacteer mij op Jami + + + + My Id is : + Mijn ID is: + + + + %1 + %1 is the contact username + %1 + + + + %1 + %1 is the contact unique identifier + %1 + + + + Call incoming from %1 + Inkomende oproep van %1 + + + + DeleteAccountDialog + + + Account deletion + Accountverwijdering + + + + Do you really want to delete the following account? + Weet u zeker dat u de volgende account wilt verwijderen? + + + + If this account hasn't been exported, or added to another device, it will be irrevocably lost. + Als deze account nog niet geëxporteerd is of nog niet toegevoegd is aan een ander apparaat, zal hij onherroepelijk verloren gaan + + + + Permanently delete account + Account voorgoed verwijderen + + + + Delete + Verwijderen + + + + Cancel account deletion + Accountverwijdering annuleren + + + + Cancel + Annuleren + + + + DeviceItemWidget + + + Form + Formulier + + + + Device Id + Apparaats-ID + + + + this device + dit apparaat + + + + InviteButtonsWidget + + + Accept + Aanvaarden + + + + Refuse + Afwijzen + + + + Block + Blokkeren + + + + LinkDeviceDialog + + + Dialog + Dialoog + + + + Enter your account password + Geef uw accountpaswoord in + + + + Password + Paswoord + + + + Ok + Oké + + + + Cancel + Annuleren + + + + Exporting account + Account wordt geëxporteerd + + + + Your PIN is + Uw pincode is + + + + PIN + Pincode + + + + This pin and the account password should be entered in your device within 10 minutes. + U moet deze pincode en het accountpaswoord binnen de 10 minuten op uw nieuwe apparaat ingeven. + + + + Close + Sluiten + + + + Link Another Device + Een ander apparaat koppelen + + + + Incorrect password + Verkeerd paswoord + + + + Something went wrong. +Please try again later. + Er is iets misgegaan. +Herprobeer het later. + + + + MainWindow + + + Settings + Instellingen + + + + Exit + Afsluiten + + + + About + Over + + + + Jami + Jami + + + + NameRegistrationDialog + + + Set Registered Name + Stel geregistreerde naam in + + + + Enter your account password + Geef uw accountpaswoord in + + + + Password text input + Paswoordtekstingave + + + + Password text entry + Paswoordtekstingave + + + + Password + Paswoord + + + + Register + Registreren + + + + Cancel + Annuleren + + + + Registering Name + Naam wordt geregistreerd + + + + Something went wrong + Er is iets misgegaan + + + + Close + Sluiten + + + + Incorrect password + Verkeerd paswoord + + + + Network error + Netwerkfout + + + + NewWizardWidget + + + Form + Formulier + + + + Welcome Label + Welkomstlabel + + + + Welcome to + Welkom bij + + + + Welcome Logo + Welkomstlogo + + + + Create Jami account button + Knop Jami-account aanmaken + + + + Push button for Jami account creation start trigger + Trekker voor starten van aanmaken van Jami-account na druk op knop + + + + Create a Jami account + Een Jami-account aanmaken + + + + Link device button + Knop apparaat koppelen + + + + Push button for device linkage start trigger + Trekker voor koppelen van apparaat na druk op knop + + + + Link this device to an account + Dit apparaat aan een account koppelen + + + + Create Jami SIP account button + Knop Jami-SIP-account aanmaken + + + + Push button for Jami SIP account creation start trigger + Trekker voor starten van aanmaken van Jami-SIP-account na druk op knop + + + + Create a SIP account + Maak een SIP-account aan + + + + Link this device to an existing account + Dit apparaat aan een bestaande account koppelen + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Ubuntu'; font-size:14px; color:#555555;">To link this device to another account, you first </span><span style=" font-family:'Ubuntu'; font-size:14px; font-weight:600; color:#555555;">need to obtain a PIN</span><span style=" font-family:'Ubuntu'; font-size:14px; color:#555555;"> code. To generate the PIN code:</span></p> +<ol style="margin-top: 0px; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; -qt-list-indent: 1;"><li style=" font-family:'Ubuntu'; font-size:14px; color:#555555;" style=" margin-top:12px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:14px;">Go to the </span><span style=" font-size:14px; font-weight:600;">Account management setting</span><span style=" font-size:14px;"> of a previous device</span></li> +<li style=" font-family:'Ubuntu'; font-size:14px; color:#555555;" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:14px;">Choose the </span><span style=" font-size:14px; font-weight:600;">Jami account</span><span style=" font-size:14px;"> you want to use</span></li> +<li style=" font-family:'Ubuntu'; font-size:14px; color:#555555;" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:14px;">Go to the </span><span style=" font-size:14px; font-weight:600;">Devices</span><span style=" font-size:14px;"> tab</span></li> +<li style=" font-family:'Ubuntu'; font-size:14px; color:#555555;" style=" margin-top:0px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:14px;">Select </span><span style=" font-size:14px; font-weight:600;">Add a device</span></li></ol> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Ubuntu'; font-size:14px; color:#555555;">You will get the necessary PIN to complete this form. The PIN is only valid for </span><span style=" font-family:'Ubuntu'; font-size:14px; font-weight:600; color:#555555;">10 minutes</span><span style=" font-family:'Ubuntu'; font-size:10px; color:#555555;">.</span></p></body></html> + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Ubuntu'; font-size:14px; color:#555555;">Om dit apparaat aan een andere account te koppelen, moet u eerst </span><span style=" font-family:'Ubuntu'; font-size:14px; font-weight:600; color:#555555;">een pincode verkrijgen</span><span style=" font-family:'Ubuntu'; font-size:14px; color:#555555;">. Om de pincode te genereren:</span></p> +<ol style="margin-top: 0px; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; -qt-list-indent: 1;"><li style=" font-family:'Ubuntu'; font-size:14px; color:#555555;" style=" margin-top:12px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:14px;">Ga naar de </span><span style=" font-size:14px; font-weight:600;">Accountbeheerinstellingen</span><span style=" font-size:14px;"> van een vorig apparaat</span></li> +<li style=" font-family:'Ubuntu'; font-size:14px; color:#555555;" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:14px;">Kies de </span><span style=" font-size:14px; font-weight:600;">Jami-account</span><span style=" font-size:14px;"> die u wilt gebruiken</span></li> +<li style=" font-family:'Ubuntu'; font-size:14px; color:#555555;" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:14px;">Ga naar het tabblad </span><span style=" font-size:14px; font-weight:600;">Apparaten</span><span style=" font-size:14px;"></span></li> +<li style=" font-family:'Ubuntu'; font-size:14px; color:#555555;" style=" margin-top:0px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:14px;">Selecteer </span><span style=" font-size:14px; font-weight:600;">Een apparaat toevoegen</span></li></ol> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Ubuntu'; font-size:14px; color:#555555;">U zult de pincode krijgen die u nodig heeft om dit proces te voltooien. De pincode is slechts </span><span style=" font-family:'Ubuntu'; font-size:14px; font-weight:600; color:#555555;">10 minuten</span><span style=" font-family:'Ubuntu'; font-size:10px; color:#555555;"> geldig.</span></p></body></html> + + + + Enter your pin: + Geef uw pincode in: + + + + Or import a file: + Of importeer een bestand: + + + + Link from exported account archive file + Koppelen van geëxporteerd accountarchiefbestand + + + + + + (None) + (geen) + + + + Password: + Paswoord: + + + + + Profile + Profiel + + + + + Profile name + Profielnaam + + + + Account + Account + + + + Register your username. +This will reserve the username so that only you can use it. +Your friends will be able to call you with your usename +instead of using your ID. + Registreer uw gebruikersnaam. +Dit zal de gebruikersnaam registreren, zodat enkel u ze kunt gebruiken. +Uw vrienden zullen u kunnen bellen met uw gebruikersnaam +in plaats van uw Ring-ID. + + + + Public username checkbox + Selectievakje openbare gebruikersnaam + + + + Checkbox selecting if the user wants a public username + Selectievakje om te kiezen of de gebruiker een openbare gebruikersnaam wil + + + + Register public username + Registreer een openbare gebruikersnaam + + + + Public username edit + Bewerken openbare gebruikersnaam + + + + Choose your username + Kies uw gebruikersnaam + + + + Password text input + Paswoordtekstingave + + + + Password text entry + Paswoordtekstingave + + + + + Password + Paswoord + + + + + Password confirmation text input + Paswoordbevestigingstekstingave + + + + Confirm password + Bevestig paswoord + + + + SIP Account + SIP-account + + + + SIP Server edit + SIP-server bewerken + + + + Server + Server + + + + SIP proxy input + SIP-proxy-ingave + + + + SIP proxy text entry + SIP-proxy-tekstingave + + + + Proxy + Proxy + + + + SIP username input + SIP-gebruikersnaamingave + + + + SIP Password text entry + SIP-paswoord-tekstingave + + + + Username + Gebruikersnaam + + + + + SIP Password text input + SIP-paswoord-tekstingave + + + + Generating your Jami account… + Uw Jami-account wordt aangemaakt… + + + + Previous page button + Knop vorig blad + + + + push button to access previous page of wizard + druk op de knop om naar het vorige blad van de assistent te gaan + + + + Previous + Vorige + + + + Cancel account create/link + Aanmaken/koppelen van account annuleren + + + + push button to cancel account creation or linking + trekker voor annuleren van aanmaken of verwijderen van account + + + + Back + Terug + + + + Next page Button + Knop volgend blad + + + + Push button to access next page of wizard + Druk op de knop om naar het volgende blad van de assistent te gaan + + + + Next + Volgende + + + + Open File + Bestand openen + + + + Jami archive files (*.gz); All files (*) + Jami-archiefbestanden (*.gz); Alle bestanden (*) + + + + Your account needs to be migrated. Enter your password. + Uw account moet gemigreerd worden. Geef uw paswoord in. + + + + Migrating your Jami account... + Uw Jami-account wordt gemigreerd… + + + + Importing account archive... + Accountarchief importeren… + + + + Generating your Jami account... + Uw Jami-account wordt aangemaakt… + + + + Generating your SIP account... + Uw SIP-account wordt gegenereerd… + + + + Error creating account + Fout bij aanmaken van account + + + + PasswordDialog + + + Change Account Password + Accountpaswoord wijzigen + + + + Enter Current Password + Geef huidig paswoord in + + + + Enter New Password + Geef nieuw paswoord in + + + + Confirm New Password + Bevestig nieuw paswoord + + + + Confirm + Bevestigen + + + + Cancel + Annuleren + + + + Current Password Incorrect + Huidig paswoord is verkeerd + + + + PhotoBoothDialog + + + Photobooth + Fotoautomaat + + + + PhotoboothWidget + + + Form + Formulier + + + + Photobooth display + Fotoautomaatweergave + + + + Choose File + Bestand kiezen + + + + Image Files (*.jpg *.jpeg *.png) + Afbeeldingsbestanden (*.jpg *.jpeg *.png) + + + + PrivateBridging + + + Choose File + Bestand kiezen + + + + Files (*) + Bestanden (*) + + + + QObject + + + No default mail client found + Geen standaard-e-mailprogramma gevonden + + + + + Edit Device Name + Apparaatnaam bewerken + + + + Unlink Device From Account + Apparaat ontkoppelen van account + + + + Save new device name + Nieuwe apparaatsnaam opslaan + + + + Add as contact + Toevoegen aan contacten + + + + RingButton + + + Select folder + Kies een map + + + + SettingsWidget + + + Form + Formulier + + + + Settings + Instellingen + + + + Account + Account + + + + + General + Algemeen + + + + + Audio / Video + Audio/video + + + + System + Systeem + + + + Enable desktop notifications + Bureaubladmeldingen inschakelen + + + + Keep minimized on close + Minimaliseren bij sluiten + + + + Download folder + Downloadmap + + + + Save in + Opslaan in + + + + Always Recording + Altijd opnemen + + + + Updates + Updates + + + + Check for updates automatically every + Automatisch controleren op updates elke + + + + Interval between update checks in days selector + Selectie interval in dagen tussen controles op updates + + + + days + dagen + + + + Check for updates now button + Knop nu controleren op updates + + + + Check for updates now + Nu controleren op updates + + + + Password + Paswoord + + + + + Enable + Inschakelen + + + + toggle enable notifications + schakelaar meldingen inschakelen + + + + Toggle keep minimized on close + Schakelaar minimaliseren bij sluiten + + + + Call Recordings + Gespreksopnames + + + + Toggle automatic updates + Schakelaar automatische updates + + + + Jami Account + Jami-account + + + + + Profile + Profiel + + + + + Identity + Identiteit + + + + Id + ID + + + + Registered name + Geregistreerde naam + + + + Type here to register a username + Typ hier om een gebruikersnaam te registreren + + + + Register + Registreren + + + + Change Password + Paswoord wijzigen + + + + Export Account + Account exporteren + + + + + Delete Account + Account verwijderen + + + + Linked Devices + Gekoppelde apparaten + + + + Link Another Device + Een ander apparaat koppelen + + + + Banned Contacts + Geblokkeerde contacten + + + + Format + Formaat + + + + Video device framerate selector + Framerateselectie video-apparaat + + + + Preview unavailable + Voorbeeld onbeschikbaar + + + + + Advanced Account Settings + Geavanceerde accountinstellingen + + + + SIP Account + SIP-account + + + + Username + Gebruikersnaam + + + + Hostname + Hostnaam + + + + Proxy + Proxy + + + + Audio + Geluid + + + + Microphone + Microfoon + + + + Audio input device selector + Selectie audio-invoerapparaat + + + + Output Device + Uitvoerapparaat + + + + Choose the output device + Kies het uitvoerapparaat + + + + Video + Video + + + + Device + Apparaat + + + + Video device selector + Selectie video-apparaat + + + + A registered name should not have any spaces and must be at least three letters long + Een geregistreerde naam mag geen spaties bevatten, en moet minstens drie tekens lang zijn + + + + This name is already taken + Deze naam is reeds in gebruik + + + + + Enter an alias + Geef een alias in + + + + Register this name + Deze naam registreren + + + + Remove Device + Apparaat verwijderen + + + + Enter this account's password to confirm the removal of this device + Geef het paswoord van deze account in om het verwijderen van dit apparaat te bevestigen + + + + Are you sure you wish to remove this device? + Weet u zeker dat u dit apparaat wilt verwijderen? + + + + Export Account Here + Account hier exporteren + + + + Select A Folder For Your Downloads + Selecteer een map voor uw downloads + + + + Select A Folder For Your Recordings + Kies een map voor uw opnamen + + + + VideoOverlay + + + Call on Hold + Telefoongesprek in wacht + + + + Hold / Unhold + In wacht zetten / uit wacht halen + + + + Chat + Chat + + + + Mute Mic + Microfoon dempen + + + + Record call + Gesprek opnemen + + + + Name label + Naamlabel + + + + Time elapsed + Tijd verstreken + + + + 00:00 + 00:00 + + + + Hangup + Ophangen + + + + Mute Video + Video uitschakelen + + + + VideoView + + + Share entire screen + Scherm delen + + + + Share screen area + Schermgebied delen + + + + Share file + Bestand delen + + + \ No newline at end of file diff --git a/translations/ring_client_windows_nl_NL.ts b/translations/ring_client_windows_nl_NL.ts new file mode 100644 index 00000000..d9457e98 --- /dev/null +++ b/translations/ring_client_windows_nl_NL.ts @@ -0,0 +1,1589 @@ + + + AboutDialog + + + + About + + + + + about button + + + + + credits button + + + + + Credits + + + + + Free as in Freedom + + + + + The Microsoft Windows client for Jami. +Jami is a secured and distributed communication software. + + + + + version + + + + + Created by: + + + + + Artwork by: + + + + + Based on the SFLPhone project + + + + + AccountItemDelegate + + + Add Account + + + + + AdvancedSIPSettingsWidget + + + Form + + + + + Call Settings + + + + + Auto Answer Calls + + + + + Enable Custom Ringtone + + + + + Connectivity + + + + + STUN Address + + + + + Use STUN + + + + + Use UPnP + + + + + Use TURN + + + + + TURN Password + + + + + TURN Username + + + + + TURN Address + + + + + Media + Media + + + + Enable Video + + + + + Video Codecs + + + + + Audio Codecs + + + + + Audio Files (*.wav *.ogg *.opus *.mp3 *aiff *wma) + + + + + Add a custom ringtone + + + + + AdvancedSettingsWidget + + + Form + + + + + Call Settings + + + + + Allow Calls From Untrusted Peers + + + + + Auto Answer Calls + + + + + Enable Custom Ringtone + + + + + Add a custom ringtone + + + + + Name Server + + + + + Address + + + + + OpenDHT Configuration + + + + + Enable Proxy + + + + + Bootstrap + + + + + Security + Beveiliging + + + + Private Key Password + + + + + User Certificate + + + + + Private Key + + + + + CA Certificate + + + + + Connectivity + + + + + Use STUN + + + + + STUN Address + + + + + Use UPnP + + + + + Use TURN + + + + + TURN Password + + + + + TURN Username + + + + + TURN Address + + + + + Media + Media + + + + Enable Video + + + + + Audio Codecs + + + + + Video Codecs + + + + + Audio Files (*.wav *.ogg *.opus *.mp3 *aiff *wma) + + + + + AnimatedOverlay + + + Form + + + + + BannedItemWidget + + + Form + + + + + name + + + + + id + + + + + CallWidget + + + Show conversations + + + + + Conversations + + + + + Search contact text input + + + + + Jami is free software for universal communication which respects the freedoms and privacy of its users. + + + + + + This is your ID. +Copy and share it with your friends! + + + + + + Show ring ID QR code + + + + + Share ring ID button + + + + + Double-click to copy + + + + + Error while generating QR Code + + + + + + best name + + + + + best Id + + + + + Back to homepage button + + + + + Add to contacts + Voeg toe aan contacten + + + + Show invites + + + + + Invites + + + + + + Find a new or existing contact + + + + + Wants to talk to you! + + + + + Answer incoming call button + + + + + Ignore incoming call button + + + + + Answer + + + + + Ignore + + + + + Cancel outgoing call + + + + + Cancel + + + + + Start video call + + + + + Start audio call + + + + + Clear conversation + + + + + Remove contact + + + + + Block contact + + + + + Copy number + Kopieër nummer + + + + Search your received invitations + + + + + Contact me on Jami + + + + + My Id is : + + + + + %1 + %1 is the contact username + + + + + %1 + %1 is the contact unique identifier + + + + + Call incoming from %1 + + + + + DeleteAccountDialog + + + Account deletion + + + + + Do you really want to delete the following account? + + + + + If this account hasn't been exported, or added to another device, it will be irrevocably lost. + + + + + Permanently delete account + + + + + Delete + Verwijderen + + + + Cancel account deletion + + + + + Cancel + + + + + DeviceItemWidget + + + Form + + + + + Device Id + + + + + this device + + + + + InviteButtonsWidget + + + Accept + + + + + Refuse + + + + + Block + + + + + LinkDeviceDialog + + + Dialog + + + + + Enter your account password + + + + + Password + Wachtwoord + + + + Ok + + + + + Cancel + + + + + Exporting account + + + + + Your PIN is + + + + + PIN + + + + + This pin and the account password should be entered in your device within 10 minutes. + + + + + Close + + + + + Link Another Device + + + + + Incorrect password + + + + + Something went wrong. +Please try again later. + + + + + MainWindow + + + Settings + Instellingen + + + + Exit + + + + + About + + + + + Jami + + + + + NameRegistrationDialog + + + Set Registered Name + + + + + Enter your account password + + + + + Password text input + + + + + Password text entry + + + + + Password + Wachtwoord + + + + Register + Registreren + + + + Cancel + + + + + Registering Name + + + + + Something went wrong + + + + + Close + + + + + Incorrect password + + + + + Network error + + + + + NewWizardWidget + + + Form + + + + + Welcome Label + + + + + Welcome to + + + + + Welcome Logo + + + + + Create Jami account button + + + + + Push button for Jami account creation start trigger + + + + + Create a Jami account + + + + + Link device button + + + + + Push button for device linkage start trigger + + + + + Link this device to an account + + + + + Create Jami SIP account button + + + + + Push button for Jami SIP account creation start trigger + + + + + Create a SIP account + + + + + Link this device to an existing account + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Ubuntu'; font-size:14px; color:#555555;">To link this device to another account, you first </span><span style=" font-family:'Ubuntu'; font-size:14px; font-weight:600; color:#555555;">need to obtain a PIN</span><span style=" font-family:'Ubuntu'; font-size:14px; color:#555555;"> code. To generate the PIN code:</span></p> +<ol style="margin-top: 0px; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; -qt-list-indent: 1;"><li style=" font-family:'Ubuntu'; font-size:14px; color:#555555;" style=" margin-top:12px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:14px;">Go to the </span><span style=" font-size:14px; font-weight:600;">Account management setting</span><span style=" font-size:14px;"> of a previous device</span></li> +<li style=" font-family:'Ubuntu'; font-size:14px; color:#555555;" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:14px;">Choose the </span><span style=" font-size:14px; font-weight:600;">Jami account</span><span style=" font-size:14px;"> you want to use</span></li> +<li style=" font-family:'Ubuntu'; font-size:14px; color:#555555;" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:14px;">Go to the </span><span style=" font-size:14px; font-weight:600;">Devices</span><span style=" font-size:14px;"> tab</span></li> +<li style=" font-family:'Ubuntu'; font-size:14px; color:#555555;" style=" margin-top:0px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:14px;">Select </span><span style=" font-size:14px; font-weight:600;">Add a device</span></li></ol> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Ubuntu'; font-size:14px; color:#555555;">You will get the necessary PIN to complete this form. The PIN is only valid for </span><span style=" font-family:'Ubuntu'; font-size:14px; font-weight:600; color:#555555;">10 minutes</span><span style=" font-family:'Ubuntu'; font-size:10px; color:#555555;">.</span></p></body></html> + + + + + Enter your pin: + + + + + Or import a file: + + + + + Link from exported account archive file + + + + + + + (None) + + + + + Password: + + + + + + Profile + + + + + + Profile name + + + + + Account + + + + + Register your username. +This will reserve the username so that only you can use it. +Your friends will be able to call you with your usename +instead of using your ID. + + + + + Public username checkbox + + + + + Checkbox selecting if the user wants a public username + + + + + Register public username + + + + + Public username edit + + + + + Choose your username + + + + + Password text input + + + + + Password text entry + + + + + + Password + Wachtwoord + + + + + Password confirmation text input + + + + + Confirm password + + + + + SIP Account + + + + + SIP Server edit + + + + + Server + + + + + SIP proxy input + + + + + SIP proxy text entry + + + + + Proxy + + + + + SIP username input + + + + + SIP Password text entry + + + + + Username + Gebruikersnaam + + + + + SIP Password text input + + + + + Generating your Jami account… + + + + + Previous page button + + + + + push button to access previous page of wizard + + + + + Previous + + + + + Cancel account create/link + + + + + push button to cancel account creation or linking + + + + + Back + + + + + Next page Button + + + + + Push button to access next page of wizard + + + + + Next + + + + + Open File + + + + + Jami archive files (*.gz); All files (*) + + + + + Your account needs to be migrated. Enter your password. + + + + + Migrating your Jami account... + + + + + Importing account archive... + + + + + Generating your Jami account... + + + + + Generating your SIP account... + + + + + Error creating account + + + + + PasswordDialog + + + Change Account Password + + + + + Enter Current Password + + + + + Enter New Password + + + + + Confirm New Password + + + + + Confirm + + + + + Cancel + + + + + Current Password Incorrect + + + + + PhotoBoothDialog + + + Photobooth + + + + + PhotoboothWidget + + + Form + + + + + Photobooth display + + + + + Choose File + + + + + Image Files (*.jpg *.jpeg *.png) + + + + + PrivateBridging + + + Choose File + + + + + Files (*) + + + + + QObject + + + No default mail client found + + + + + + Edit Device Name + + + + + Unlink Device From Account + + + + + Save new device name + + + + + Add as contact + + + + + RingButton + + + Select folder + + + + + SettingsWidget + + + Form + + + + + Settings + Instellingen + + + + Account + + + + + + General + Algemeen + + + + + Audio / Video + + + + + System + + + + + Enable desktop notifications + + + + + Keep minimized on close + + + + + Download folder + + + + + Save in + + + + + Always Recording + + + + + Updates + + + + + Check for updates automatically every + + + + + Interval between update checks in days selector + + + + + days + + + + + Check for updates now button + + + + + Check for updates now + + + + + Password + Wachtwoord + + + + + Enable + + + + + toggle enable notifications + + + + + Toggle keep minimized on close + + + + + Call Recordings + + + + + Toggle automatic updates + + + + + Jami Account + + + + + + Profile + + + + + + Identity + + + + + Id + + + + + Registered name + + + + + Type here to register a username + + + + + Register + Registreren + + + + Change Password + + + + + Export Account + + + + + + Delete Account + + + + + Linked Devices + + + + + Link Another Device + + + + + Banned Contacts + + + + + Format + + + + + Video device framerate selector + + + + + Preview unavailable + + + + + + Advanced Account Settings + + + + + SIP Account + + + + + Username + Gebruikersnaam + + + + Hostname + + + + + Proxy + + + + + Audio + Geluid + + + + Microphone + + + + + Audio input device selector + + + + + Output Device + + + + + Choose the output device + + + + + Video + Beeld + + + + Device + + + + + Video device selector + + + + + A registered name should not have any spaces and must be at least three letters long + + + + + This name is already taken + + + + + + Enter an alias + + + + + Register this name + + + + + Remove Device + + + + + Enter this account's password to confirm the removal of this device + + + + + Are you sure you wish to remove this device? + + + + + Export Account Here + + + + + Select A Folder For Your Downloads + + + + + Select A Folder For Your Recordings + + + + + VideoOverlay + + + Call on Hold + + + + + Hold / Unhold + + + + + Chat + + + + + Mute Mic + + + + + Record call + + + + + Name label + + + + + Time elapsed + + + + + 00:00 + + + + + Hangup + + + + + Mute Video + + + + + VideoView + + + Share entire screen + + + + + Share screen area + + + + + Share file + + + + \ No newline at end of file diff --git a/translations/ring_client_windows_oc.ts b/translations/ring_client_windows_oc.ts new file mode 100644 index 00000000..0a5d2e50 --- /dev/null +++ b/translations/ring_client_windows_oc.ts @@ -0,0 +1,1589 @@ + + + AboutDialog + + + + About + A prepaus + + + + about button + + + + + credits button + + + + + Credits + Crèdit + + + + Free as in Freedom + Liure coma la libertat + + + + The Microsoft Windows client for Jami. +Jami is a secured and distributed communication software. + + + + + version + + + + + Created by: + + + + + Artwork by: + + + + + Based on the SFLPhone project + + + + + AccountItemDelegate + + + Add Account + + + + + AdvancedSIPSettingsWidget + + + Form + + + + + Call Settings + + + + + Auto Answer Calls + + + + + Enable Custom Ringtone + + + + + Connectivity + Connectivitat + + + + STUN Address + + + + + Use STUN + Utilizar STUN + + + + Use UPnP + + + + + Use TURN + Utilizar TURN + + + + TURN Password + + + + + TURN Username + + + + + TURN Address + + + + + Media + Mèdia + + + + Enable Video + + + + + Video Codecs + + + + + Audio Codecs + + + + + Audio Files (*.wav *.ogg *.opus *.mp3 *aiff *wma) + + + + + Add a custom ringtone + + + + + AdvancedSettingsWidget + + + Form + + + + + Call Settings + + + + + Allow Calls From Untrusted Peers + + + + + Auto Answer Calls + + + + + Enable Custom Ringtone + + + + + Add a custom ringtone + + + + + Name Server + + + + + Address + Adreça + + + + OpenDHT Configuration + + + + + Enable Proxy + Activar lo servidor mandatari + + + + Bootstrap + + + + + Security + Seguretat + + + + Private Key Password + + + + + User Certificate + + + + + Private Key + + + + + CA Certificate + + + + + Connectivity + Connectivitat + + + + Use STUN + Utilizar STUN + + + + STUN Address + + + + + Use UPnP + + + + + Use TURN + Utilizar TURN + + + + TURN Password + + + + + TURN Username + + + + + TURN Address + + + + + Media + Mèdia + + + + Enable Video + + + + + Audio Codecs + + + + + Video Codecs + + + + + Audio Files (*.wav *.ogg *.opus *.mp3 *aiff *wma) + + + + + AnimatedOverlay + + + Form + + + + + BannedItemWidget + + + Form + + + + + name + + + + + id + + + + + CallWidget + + + Show conversations + + + + + Conversations + Discutidas + + + + Search contact text input + + + + + Jami is free software for universal communication which respects the freedoms and privacy of its users. + Jami es un logicial liure per comunicacions universalas que respèctan la libertat e la vida privada de sos utilizaires. + + + + + This is your ID. +Copy and share it with your friends! + + + + + + Show ring ID QR code + + + + + Share ring ID button + + + + + Double-click to copy + + + + + Error while generating QR Code + + + + + + best name + + + + + best Id + + + + + Back to homepage button + + + + + Add to contacts + + + + + Show invites + + + + + Invites + + + + + + Find a new or existing contact + + + + + Wants to talk to you! + + + + + Answer incoming call button + + + + + Ignore incoming call button + + + + + Answer + + + + + Ignore + Ignorar + + + + Cancel outgoing call + + + + + Cancel + anullar + + + + Start video call + + + + + Start audio call + + + + + Clear conversation + + + + + Remove contact + + + + + Block contact + Blocar contacte + + + + Copy number + + + + + Search your received invitations + + + + + Contact me on Jami + + + + + My Id is : + + + + + %1 + %1 is the contact username + + + + + %1 + %1 is the contact unique identifier + + + + + Call incoming from %1 + + + + + DeleteAccountDialog + + + Account deletion + + + + + Do you really want to delete the following account? + + + + + If this account hasn't been exported, or added to another device, it will be irrevocably lost. + + + + + Permanently delete account + + + + + Delete + Suprimir + + + + Cancel account deletion + + + + + Cancel + anullar + + + + DeviceItemWidget + + + Form + + + + + Device Id + + + + + this device + + + + + InviteButtonsWidget + + + Accept + Acceptar + + + + Refuse + Refusar + + + + Block + Blocar + + + + LinkDeviceDialog + + + Dialog + + + + + Enter your account password + + + + + Password + Senha + + + + Ok + D’acòrdi + + + + Cancel + anullar + + + + Exporting account + + + + + Your PIN is + + + + + PIN + PIN + + + + This pin and the account password should be entered in your device within 10 minutes. + + + + + Close + + + + + Link Another Device + + + + + Incorrect password + Marrit senhal + + + + Something went wrong. +Please try again later. + + + + + MainWindow + + + Settings + Paramètres + + + + Exit + + + + + About + A prepaus + + + + Jami + Jami + + + + NameRegistrationDialog + + + Set Registered Name + + + + + Enter your account password + + + + + Password text input + + + + + Password text entry + + + + + Password + Senha + + + + Register + + + + + Cancel + anullar + + + + Registering Name + + + + + Something went wrong + + + + + Close + + + + + Incorrect password + Marrit senhal + + + + Network error + Error ret + + + + NewWizardWidget + + + Form + + + + + Welcome Label + + + + + Welcome to + + + + + Welcome Logo + + + + + Create Jami account button + + + + + Push button for Jami account creation start trigger + + + + + Create a Jami account + Crear un compte Jami + + + + Link device button + + + + + Push button for device linkage start trigger + + + + + Link this device to an account + Associar aqueste aparelh a un compte + + + + Create Jami SIP account button + + + + + Push button for Jami SIP account creation start trigger + + + + + Create a SIP account + + + + + Link this device to an existing account + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Ubuntu'; font-size:14px; color:#555555;">To link this device to another account, you first </span><span style=" font-family:'Ubuntu'; font-size:14px; font-weight:600; color:#555555;">need to obtain a PIN</span><span style=" font-family:'Ubuntu'; font-size:14px; color:#555555;"> code. To generate the PIN code:</span></p> +<ol style="margin-top: 0px; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; -qt-list-indent: 1;"><li style=" font-family:'Ubuntu'; font-size:14px; color:#555555;" style=" margin-top:12px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:14px;">Go to the </span><span style=" font-size:14px; font-weight:600;">Account management setting</span><span style=" font-size:14px;"> of a previous device</span></li> +<li style=" font-family:'Ubuntu'; font-size:14px; color:#555555;" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:14px;">Choose the </span><span style=" font-size:14px; font-weight:600;">Jami account</span><span style=" font-size:14px;"> you want to use</span></li> +<li style=" font-family:'Ubuntu'; font-size:14px; color:#555555;" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:14px;">Go to the </span><span style=" font-size:14px; font-weight:600;">Devices</span><span style=" font-size:14px;"> tab</span></li> +<li style=" font-family:'Ubuntu'; font-size:14px; color:#555555;" style=" margin-top:0px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:14px;">Select </span><span style=" font-size:14px; font-weight:600;">Add a device</span></li></ol> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Ubuntu'; font-size:14px; color:#555555;">You will get the necessary PIN to complete this form. The PIN is only valid for </span><span style=" font-family:'Ubuntu'; font-size:14px; font-weight:600; color:#555555;">10 minutes</span><span style=" font-family:'Ubuntu'; font-size:10px; color:#555555;">.</span></p></body></html> + + + + + Enter your pin: + + + + + Or import a file: + + + + + Link from exported account archive file + + + + + + + (None) + (Cap) + + + + Password: + + + + + + Profile + Perfil + + + + + Profile name + + + + + Account + Compte + + + + Register your username. +This will reserve the username so that only you can use it. +Your friends will be able to call you with your usename +instead of using your ID. + + + + + Public username checkbox + + + + + Checkbox selecting if the user wants a public username + + + + + Register public username + + + + + Public username edit + + + + + Choose your username + + + + + Password text input + + + + + Password text entry + + + + + + Password + Senha + + + + + Password confirmation text input + + + + + Confirm password + Confirmar lo senhal + + + + SIP Account + + + + + SIP Server edit + + + + + Server + + + + + SIP proxy input + + + + + SIP proxy text entry + + + + + Proxy + Servidor mandatari + + + + SIP username input + + + + + SIP Password text entry + + + + + Username + Nom d’utilizaire + + + + + SIP Password text input + + + + + Generating your Jami account… + Generacion del compte Jami… + + + + Previous page button + + + + + push button to access previous page of wizard + + + + + Previous + Precedent + + + + Cancel account create/link + + + + + push button to cancel account creation or linking + + + + + Back + Tornar + + + + Next page Button + + + + + Push button to access next page of wizard + + + + + Next + Seguent + + + + Open File + + + + + Jami archive files (*.gz); All files (*) + + + + + Your account needs to be migrated. Enter your password. + + + + + Migrating your Jami account... + + + + + Importing account archive... + + + + + Generating your Jami account... + + + + + Generating your SIP account... + + + + + Error creating account + + + + + PasswordDialog + + + Change Account Password + + + + + Enter Current Password + + + + + Enter New Password + + + + + Confirm New Password + + + + + Confirm + + + + + Cancel + anullar + + + + Current Password Incorrect + + + + + PhotoBoothDialog + + + Photobooth + + + + + PhotoboothWidget + + + Form + + + + + Photobooth display + + + + + Choose File + + + + + Image Files (*.jpg *.jpeg *.png) + + + + + PrivateBridging + + + Choose File + + + + + Files (*) + + + + + QObject + + + No default mail client found + + + + + + Edit Device Name + + + + + Unlink Device From Account + + + + + Save new device name + + + + + Add as contact + + + + + RingButton + + + Select folder + + + + + SettingsWidget + + + Form + + + + + Settings + Paramètres + + + + Account + Compte + + + + + General + General + + + + + Audio / Video + + + + + System + Sistèma + + + + Enable desktop notifications + + + + + Keep minimized on close + + + + + Download folder + Dossièr de telecargament + + + + Save in + + + + + Always Recording + + + + + Updates + + + + + Check for updates automatically every + + + + + Interval between update checks in days selector + + + + + days + + + + + Check for updates now button + + + + + Check for updates now + + + + + Password + Senha + + + + + Enable + + + + + toggle enable notifications + + + + + Toggle keep minimized on close + + + + + Call Recordings + + + + + Toggle automatic updates + + + + + Jami Account + + + + + + Profile + Perfil + + + + + Identity + + + + + Id + + + + + Registered name + + + + + Type here to register a username + + + + + Register + + + + + Change Password + + + + + Export Account + + + + + + Delete Account + + + + + Linked Devices + + + + + Link Another Device + + + + + Banned Contacts + + + + + Format + + + + + Video device framerate selector + + + + + Preview unavailable + + + + + + Advanced Account Settings + + + + + SIP Account + + + + + Username + Nom d’utilizaire + + + + Hostname + + + + + Proxy + Servidor mandatari + + + + Audio + Àudio + + + + Microphone + + + + + Audio input device selector + + + + + Output Device + + + + + Choose the output device + + + + + Video + Vidèo + + + + Device + Periferic + + + + Video device selector + + + + + A registered name should not have any spaces and must be at least three letters long + + + + + This name is already taken + + + + + + Enter an alias + + + + + Register this name + + + + + Remove Device + + + + + Enter this account's password to confirm the removal of this device + + + + + Are you sure you wish to remove this device? + + + + + Export Account Here + + + + + Select A Folder For Your Downloads + + + + + Select A Folder For Your Recordings + + + + + VideoOverlay + + + Call on Hold + + + + + Hold / Unhold + + + + + Chat + Conversacion + + + + Mute Mic + + + + + Record call + + + + + Name label + + + + + Time elapsed + + + + + 00:00 + + + + + Hangup + + + + + Mute Video + + + + + VideoView + + + Share entire screen + + + + + Share screen area + + + + + Share file + + + + \ No newline at end of file diff --git a/translations/ring_client_windows_pa.ts b/translations/ring_client_windows_pa.ts new file mode 100644 index 00000000..1ab8496f --- /dev/null +++ b/translations/ring_client_windows_pa.ts @@ -0,0 +1,1589 @@ + + + AboutDialog + + + + About + + + + + about button + + + + + credits button + + + + + Credits + ਸ਼ਲਾਘਾਯੋਗ ਵਿਅਕਤੀ + + + + Free as in Freedom + + + + + The Microsoft Windows client for Jami. +Jami is a secured and distributed communication software. + + + + + version + + + + + Created by: + + + + + Artwork by: + + + + + Based on the SFLPhone project + + + + + AccountItemDelegate + + + Add Account + + + + + AdvancedSIPSettingsWidget + + + Form + + + + + Call Settings + + + + + Auto Answer Calls + + + + + Enable Custom Ringtone + + + + + Connectivity + + + + + STUN Address + + + + + Use STUN + + + + + Use UPnP + + + + + Use TURN + TURN ਵਰਤੋ + + + + TURN Password + + + + + TURN Username + + + + + TURN Address + + + + + Media + ਮੀਡੀਆ + + + + Enable Video + ਵੀਡੀਓ ਚਾਲੂ ਕਰੋ + + + + Video Codecs + + + + + Audio Codecs + + + + + Audio Files (*.wav *.ogg *.opus *.mp3 *aiff *wma) + + + + + Add a custom ringtone + + + + + AdvancedSettingsWidget + + + Form + + + + + Call Settings + + + + + Allow Calls From Untrusted Peers + + + + + Auto Answer Calls + + + + + Enable Custom Ringtone + + + + + Add a custom ringtone + + + + + Name Server + + + + + Address + + + + + OpenDHT Configuration + + + + + Enable Proxy + + + + + Bootstrap + ਬੂਟਸਟ੍ਰੈਪ + + + + Security + ਸੁਰੱਖਿਆ + + + + Private Key Password + ਨਿੱਜੀ ਕੁੰਜੀ ਪਾਸਵਰਡ + + + + User Certificate + + + + + Private Key + + + + + CA Certificate + + + + + Connectivity + + + + + Use STUN + + + + + STUN Address + + + + + Use UPnP + + + + + Use TURN + TURN ਵਰਤੋ + + + + TURN Password + + + + + TURN Username + + + + + TURN Address + + + + + Media + ਮੀਡੀਆ + + + + Enable Video + ਵੀਡੀਓ ਚਾਲੂ ਕਰੋ + + + + Audio Codecs + + + + + Video Codecs + + + + + Audio Files (*.wav *.ogg *.opus *.mp3 *aiff *wma) + + + + + AnimatedOverlay + + + Form + + + + + BannedItemWidget + + + Form + + + + + name + + + + + id + + + + + CallWidget + + + Show conversations + + + + + Conversations + ਗੱਲਾਂਬਾਤਾਂ + + + + Search contact text input + + + + + Jami is free software for universal communication which respects the freedoms and privacy of its users. + Jami ਦੁਨੀਆ ਭਰ ਵਿੱਚ ਸੰਚਾਰ ਕਰਨ ਲਈ ਮੁਫ਼ਤ ਸਾਫ਼ਟਵੇਅਰ ਹੈ ਜੋ ਆਪਣੇ ਵਰਤੋਂਕਾਰਾਂ ਦੀ ਅਜ਼ਾਦੀ ਅਤੇ ਪਰਦੇਦਾਰੀ ਦਾ ਖਿਆਲ ਰੱਖਦਾ ਹੈ। + + + + + This is your ID. +Copy and share it with your friends! + + + + + + Show ring ID QR code + + + + + Share ring ID button + + + + + Double-click to copy + + + + + Error while generating QR Code + + + + + + best name + + + + + best Id + + + + + Back to homepage button + + + + + Add to contacts + ਸੰਪਰਕਾਂ ਵਿੱਚ ਸ਼ਾਮਲ ਕਰੋ + + + + Show invites + + + + + Invites + + + + + + Find a new or existing contact + + + + + Wants to talk to you! + + + + + Answer incoming call button + + + + + Ignore incoming call button + + + + + Answer + + + + + Ignore + + + + + Cancel outgoing call + + + + + Cancel + ਰੱਦ ਕਰੋ + + + + Start video call + + + + + Start audio call + + + + + Clear conversation + + + + + Remove contact + + + + + Block contact + ਸੰਪਰਕ ਬਲਾਕ ਕਰੋ + + + + Copy number + ਨੰਬਰ ਕਾਪੀ ਕਰੋ + + + + Search your received invitations + + + + + Contact me on Jami + + + + + My Id is : + + + + + %1 + %1 is the contact username + + + + + %1 + %1 is the contact unique identifier + + + + + Call incoming from %1 + + + + + DeleteAccountDialog + + + Account deletion + + + + + Do you really want to delete the following account? + + + + + If this account hasn't been exported, or added to another device, it will be irrevocably lost. + + + + + Permanently delete account + + + + + Delete + ਮਿਟਾਓ + + + + Cancel account deletion + + + + + Cancel + ਰੱਦ ਕਰੋ + + + + DeviceItemWidget + + + Form + + + + + Device Id + + + + + this device + ਇਹ ਡੀਵਾਈਸ + + + + InviteButtonsWidget + + + Accept + ਸਵੀਕਾਰ ਕਰੋ + + + + Refuse + ਅਸਵੀਕਾਰ ਕਰੋ + + + + Block + ਬਲਾਕ ਕਰੋ + + + + LinkDeviceDialog + + + Dialog + + + + + Enter your account password + + + + + Password + ਪਾਸਵਰਡ + + + + Ok + ਠੀਕ ਹੈ + + + + Cancel + ਰੱਦ ਕਰੋ + + + + Exporting account + + + + + Your PIN is + + + + + PIN + ਪਿੰਨ + + + + This pin and the account password should be entered in your device within 10 minutes. + + + + + Close + + + + + Link Another Device + + + + + Incorrect password + + + + + Something went wrong. +Please try again later. + + + + + MainWindow + + + Settings + ਸੈਟਿੰਗ + + + + Exit + + + + + About + + + + + Jami + Jami + + + + NameRegistrationDialog + + + Set Registered Name + + + + + Enter your account password + + + + + Password text input + + + + + Password text entry + + + + + Password + ਪਾਸਵਰਡ + + + + Register + ਪੰਜੀਕਰਨ ਕਰੋ + + + + Cancel + ਰੱਦ ਕਰੋ + + + + Registering Name + + + + + Something went wrong + + + + + Close + + + + + Incorrect password + + + + + Network error + ਨੈੱਟਵਰਕ ਗੜਬੜ + + + + NewWizardWidget + + + Form + + + + + Welcome Label + + + + + Welcome to + + + + + Welcome Logo + + + + + Create Jami account button + + + + + Push button for Jami account creation start trigger + + + + + Create a Jami account + Jami ਖਾਤਾ ਬਣਾਓ + + + + Link device button + + + + + Push button for device linkage start trigger + + + + + Link this device to an account + ਇਹ ਡੀਵਾਈਸ ਕਿਸੇ ਖਾਤੇ ਨਾਲ ਲਿੰਕ ਕਰੋ + + + + Create Jami SIP account button + + + + + Push button for Jami SIP account creation start trigger + + + + + Create a SIP account + + + + + Link this device to an existing account + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Ubuntu'; font-size:14px; color:#555555;">To link this device to another account, you first </span><span style=" font-family:'Ubuntu'; font-size:14px; font-weight:600; color:#555555;">need to obtain a PIN</span><span style=" font-family:'Ubuntu'; font-size:14px; color:#555555;"> code. To generate the PIN code:</span></p> +<ol style="margin-top: 0px; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; -qt-list-indent: 1;"><li style=" font-family:'Ubuntu'; font-size:14px; color:#555555;" style=" margin-top:12px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:14px;">Go to the </span><span style=" font-size:14px; font-weight:600;">Account management setting</span><span style=" font-size:14px;"> of a previous device</span></li> +<li style=" font-family:'Ubuntu'; font-size:14px; color:#555555;" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:14px;">Choose the </span><span style=" font-size:14px; font-weight:600;">Jami account</span><span style=" font-size:14px;"> you want to use</span></li> +<li style=" font-family:'Ubuntu'; font-size:14px; color:#555555;" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:14px;">Go to the </span><span style=" font-size:14px; font-weight:600;">Devices</span><span style=" font-size:14px;"> tab</span></li> +<li style=" font-family:'Ubuntu'; font-size:14px; color:#555555;" style=" margin-top:0px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:14px;">Select </span><span style=" font-size:14px; font-weight:600;">Add a device</span></li></ol> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Ubuntu'; font-size:14px; color:#555555;">You will get the necessary PIN to complete this form. The PIN is only valid for </span><span style=" font-family:'Ubuntu'; font-size:14px; font-weight:600; color:#555555;">10 minutes</span><span style=" font-family:'Ubuntu'; font-size:10px; color:#555555;">.</span></p></body></html> + + + + + Enter your pin: + + + + + Or import a file: + + + + + Link from exported account archive file + + + + + + + (None) + + + + + Password: + + + + + + Profile + + + + + + Profile name + + + + + Account + ਖਾਤਾ + + + + Register your username. +This will reserve the username so that only you can use it. +Your friends will be able to call you with your usename +instead of using your ID. + + + + + Public username checkbox + + + + + Checkbox selecting if the user wants a public username + + + + + Register public username + + + + + Public username edit + + + + + Choose your username + + + + + Password text input + + + + + Password text entry + + + + + + Password + ਪਾਸਵਰਡ + + + + + Password confirmation text input + + + + + Confirm password + + + + + SIP Account + + + + + SIP Server edit + + + + + Server + + + + + SIP proxy input + + + + + SIP proxy text entry + + + + + Proxy + ਪ੍ਰੌਕਸੀ + + + + SIP username input + + + + + SIP Password text entry + + + + + Username + ਵਰਤੋਂਕਾਰ ਨਾਂ + + + + + SIP Password text input + + + + + Generating your Jami account… + + + + + Previous page button + + + + + push button to access previous page of wizard + + + + + Previous + + + + + Cancel account create/link + + + + + push button to cancel account creation or linking + + + + + Back + ਪਿੱਛੇ + + + + Next page Button + + + + + Push button to access next page of wizard + + + + + Next + ਅੱਗੇ + + + + Open File + + + + + Jami archive files (*.gz); All files (*) + + + + + Your account needs to be migrated. Enter your password. + + + + + Migrating your Jami account... + + + + + Importing account archive... + + + + + Generating your Jami account... + + + + + Generating your SIP account... + + + + + Error creating account + + + + + PasswordDialog + + + Change Account Password + + + + + Enter Current Password + + + + + Enter New Password + + + + + Confirm New Password + + + + + Confirm + + + + + Cancel + ਰੱਦ ਕਰੋ + + + + Current Password Incorrect + + + + + PhotoBoothDialog + + + Photobooth + + + + + PhotoboothWidget + + + Form + + + + + Photobooth display + + + + + Choose File + + + + + Image Files (*.jpg *.jpeg *.png) + + + + + PrivateBridging + + + Choose File + + + + + Files (*) + + + + + QObject + + + No default mail client found + + + + + + Edit Device Name + + + + + Unlink Device From Account + + + + + Save new device name + + + + + Add as contact + + + + + RingButton + + + Select folder + + + + + SettingsWidget + + + Form + + + + + Settings + ਸੈਟਿੰਗ + + + + Account + ਖਾਤਾ + + + + + General + ਸਧਾਰਨ + + + + + Audio / Video + + + + + System + ਸਿਸਟਮ + + + + Enable desktop notifications + + + + + Keep minimized on close + + + + + Download folder + + + + + Save in + + + + + Always Recording + + + + + Updates + + + + + Check for updates automatically every + + + + + Interval between update checks in days selector + + + + + days + + + + + Check for updates now button + + + + + Check for updates now + + + + + Password + ਪਾਸਵਰਡ + + + + + Enable + + + + + toggle enable notifications + + + + + Toggle keep minimized on close + + + + + Call Recordings + + + + + Toggle automatic updates + + + + + Jami Account + + + + + + Profile + + + + + + Identity + ਪਛਾਣ + + + + Id + + + + + Registered name + + + + + Type here to register a username + + + + + Register + ਪੰਜੀਕਰਨ ਕਰੋ + + + + Change Password + + + + + Export Account + + + + + + Delete Account + + + + + Linked Devices + + + + + Link Another Device + + + + + Banned Contacts + + + + + Format + + + + + Video device framerate selector + + + + + Preview unavailable + + + + + + Advanced Account Settings + + + + + SIP Account + + + + + Username + ਵਰਤੋਂਕਾਰ ਨਾਂ + + + + Hostname + ਹੋਸਟਨਾਮ + + + + Proxy + ਪ੍ਰੌਕਸੀ + + + + Audio + ਆਡੀਓ + + + + Microphone + + + + + Audio input device selector + + + + + Output Device + + + + + Choose the output device + + + + + Video + ਵੀਡੀਓ + + + + Device + + + + + Video device selector + + + + + A registered name should not have any spaces and must be at least three letters long + + + + + This name is already taken + + + + + + Enter an alias + + + + + Register this name + + + + + Remove Device + + + + + Enter this account's password to confirm the removal of this device + + + + + Are you sure you wish to remove this device? + + + + + Export Account Here + + + + + Select A Folder For Your Downloads + + + + + Select A Folder For Your Recordings + + + + + VideoOverlay + + + Call on Hold + + + + + Hold / Unhold + + + + + Chat + + + + + Mute Mic + + + + + Record call + + + + + Name label + + + + + Time elapsed + + + + + 00:00 + + + + + Hangup + + + + + Mute Video + + + + + VideoView + + + Share entire screen + + + + + Share screen area + + + + + Share file + ਫ਼ਾਈਲ ਸਾਂਝੀ ਕਰੋ + + + \ No newline at end of file diff --git a/translations/ring_client_windows_pl.ts b/translations/ring_client_windows_pl.ts new file mode 100644 index 00000000..794aee8c --- /dev/null +++ b/translations/ring_client_windows_pl.ts @@ -0,0 +1,1604 @@ + + + AboutDialog + + + + About + O programie + + + + about button + przycisk o programie + + + + credits button + przycisk zasługi + + + + Credits + Podziękowania + + + + Free as in Freedom + + + + + The Microsoft Windows client for Jami. +Jami is a secured and distributed communication software. + Klient Jami dla Microsoft Windows. +Jami jest wolnym oprogramowaniem do uniwersalnej komunikacji, respektującym wolność i prywatność swoich użytkowników. + + + + version + Wersja + + + + Created by: + Stworzone przez: + + + + Artwork by: + Obrazki przez: + + + + Based on the SFLPhone project + Na podstawie projektu SFLPhone + + + + AccountItemDelegate + + + Add Account + Dodaj Konto + + + + AdvancedSIPSettingsWidget + + + Form + Forma + + + + Call Settings + Ustawienia Połączeń + + + + Auto Answer Calls + Automatycznie Odbieraj Połączenia + + + + Enable Custom Ringtone + Użyj Własnego Dzwonka + + + + Connectivity + Łączność + + + + STUN Address + Adres STUN + + + + Use STUN + Użyj STUN + + + + Use UPnP + Użyj UPnP + + + + Use TURN + Użyj TURN + + + + TURN Password + Hasło TURN + + + + TURN Username + Nazwa użytkownika TURN + + + + TURN Address + Adres TURN + + + + Media + Multimedia + + + + Enable Video + Włącz video + + + + Video Codecs + Kodeki Wideo + + + + Audio Codecs + Kodeki Audio + + + + Audio Files (*.wav *.ogg *.opus *.mp3 *aiff *wma) + Pliki Audio (*.wav *.ogg *.opus *.mp3 *aiff *wma) + + + + Add a custom ringtone + Dodaj własny dzwonek + + + + AdvancedSettingsWidget + + + Form + Forma + + + + Call Settings + Ustawienia Połączeń + + + + Allow Calls From Untrusted Peers + Zezwól Na Połączenia Od Niezaufanych Użytkowników + + + + Auto Answer Calls + Automatycznie Odbieraj Połączenia + + + + Enable Custom Ringtone + Użyj Własnego Dzwonka + + + + Add a custom ringtone + Dodaj własny dzwonek + + + + Name Server + Serwer Nazw + + + + Address + Adres + + + + OpenDHT Configuration + Konfiguracja OpenDHT + + + + Enable Proxy + Włącz proxy + + + + Bootstrap + Bootstrap + + + + Security + Zabezpieczenia + + + + Private Key Password + Hasło Klucza Prywatnego + + + + User Certificate + Certyfikat Użytkownika + + + + Private Key + Klucz Prywatny + + + + CA Certificate + Certyfikat CA + + + + Connectivity + Łączność + + + + Use STUN + Użyj STUN + + + + STUN Address + Adres STUN + + + + Use UPnP + Użyj UPnP + + + + Use TURN + Użyj TURN + + + + TURN Password + Hasło TURN + + + + TURN Username + Nazwa użytkownika TURN + + + + TURN Address + Adres TURN + + + + Media + Multimedia + + + + Enable Video + Włącz video + + + + Audio Codecs + Kodeki Audio + + + + Video Codecs + Kodeki Wideo + + + + Audio Files (*.wav *.ogg *.opus *.mp3 *aiff *wma) + Pliki Audio (*.wav *.ogg *.opus *.mp3 *aiff *wma) + + + + AnimatedOverlay + + + Form + Forma + + + + BannedItemWidget + + + Form + Forma + + + + name + nazwa + + + + id + ID + + + + CallWidget + + + Show conversations + Pokaż rozmowy + + + + Conversations + Rozmowy + + + + Search contact text input + Pole szukania kontaktów + + + + Jami is free software for universal communication which respects the freedoms and privacy of its users. + Jami jest wolnym oprogramowaniem do uniwersalnej komunikacji, respektującym wolności i prywatność swoich użytkowników. + + + + + This is your ID. +Copy and share it with your friends! + + +To jest twoje ID. +Skopiuj i podziel się ze swoimi znajomymi! + + + + Show ring ID QR code + Pokaż kod QR Jami ID + + + + Share ring ID button + Guzik dzielenia się ID Jami + + + + Double-click to copy + Kliknij dwukrotnie, aby skopiować + + + + Error while generating QR Code + Wystąpił błąd podczas generowania kodu QR. + + + + + best name + najlepsza nazwa + + + + best Id + Najlepsze ID + + + + Back to homepage button + Guzik powrotu do strony głównej + + + + Add to contacts + Dodaj do kontaków + + + + Show invites + Pokaż zaproszenia + + + + Invites + Zaprasza + + + + + Find a new or existing contact + Szukaj nowego lub istniejącego kontaktu + + + + Wants to talk to you! + Chce z tobą rozmawiać! + + + + Answer incoming call button + Guzik odbierania przychodzących rozmów + + + + Ignore incoming call button + Guzik ignorowania nadchodzących połączeń + + + + Answer + Odbierz + + + + Ignore + Zignoruj + + + + Cancel outgoing call + Anuluj połączenie wychodzące + + + + Cancel + Anuluj + + + + Start video call + Rozpocznij rozmowę wideo + + + + Start audio call + Rozpocznij połączenie głosowe + + + + Clear conversation + Wyczyść rozmowę + + + + Remove contact + Usuń kontakt + + + + Block contact + Blokuj kontakt + + + + Copy number + Skopiuj numer + + + + Search your received invitations + Szukaj odebranych zaproszeń + + + + Contact me on Jami + Skontaktuj się ze mną na Jami + + + + My Id is : + Mój identyfikator to: + + + + %1 + %1 is the contact username + %1 + + + + %1 + %1 is the contact unique identifier + %1 + + + + Call incoming from %1 + Połączenie przychodzące od %1 + + + + DeleteAccountDialog + + + Account deletion + Kasowanie konta + + + + Do you really want to delete the following account? + Czy na pewno chcesz usunąć następujące konto? + + + + If this account hasn't been exported, or added to another device, it will be irrevocably lost. + Jeżeli to konto nie zostało wyeksportowane, lub dodane do innego urządzenia, zostanie bezpowrotnie utracone. + + + + Permanently delete account + Usuń konto na zawsze + + + + Delete + Usuń + + + + Cancel account deletion + Anuluj usuwanie konta + + + + Cancel + Anuluj + + + + DeviceItemWidget + + + Form + Forma + + + + Device Id + ID Urządzenia + + + + this device + to urządzenie + + + + InviteButtonsWidget + + + Accept + Akceptuj + + + + Refuse + Odmów + + + + Block + Blokuj + + + + LinkDeviceDialog + + + Dialog + Dialog + + + + Enter your account password + Wprowadź hasło do twojego konta + + + + Password + Hasło + + + + Ok + Ok + + + + Cancel + Anuluj + + + + Exporting account + Eksportuję konto + + + + Your PIN is + Twój PIN to + + + + PIN + PIN + + + + This pin and the account password should be entered in your device within 10 minutes. + Ten pin i hasło do konta powinny zostać wprowadzone na twoim urządzeniu w ciągu 10 minut. + + + + Close + Zamknij + + + + Link Another Device + Połącz Inne Urządzenie + + + + Incorrect password + Niepoprawne hasło + + + + Something went wrong. +Please try again later. + Coś poszło nie tak. +Proszę, spróbuj ponownie. + + + + MainWindow + + + Settings + Ustawienia + + + + Exit + Wyjdź + + + + About + O + + + + Jami + Jami + + + + NameRegistrationDialog + + + Set Registered Name + Ustaw Zarejestrowaną Nazwę + + + + Enter your account password + Wprowadź hasło do twojego konta + + + + Password text input + Pole tekstowe hasła + + + + Password text entry + Wpis tekstu hasła + + + + Password + Hasło + + + + Register + Zarejestruj + + + + Cancel + Anuluj + + + + Registering Name + Rejestrowanie Nazwy + + + + Something went wrong + Coś poszło nie tak + + + + Close + Zamknij + + + + Incorrect password + Niepoprawne hasło + + + + Network error + Błąd sieci + + + + NewWizardWidget + + + Form + Forma + + + + Welcome Label + Naklejka "Witaj" + + + + Welcome to + Witaj! + + + + Welcome Logo + Logo Powitania + + + + Create Jami account button + Guzik tworzenia konta Jami + + + + Push button for Jami account creation start trigger + Guzik do rozpoczęcia tworzenia konta Jami + + + + Create a Jami account + Stwórz konto Jami + + + + Link device button + Guzik łączenia urządzenia + + + + Push button for device linkage start trigger + Guzik do rozpoczęcia połączenia urządzenia + + + + Link this device to an account + Połącz to urządzenie z kontem + + + + Create Jami SIP account button + Guzik tworzenia konta SIP Jami + + + + Push button for Jami SIP account creation start trigger + + + + + Create a SIP account + Stwórz konto SIP + + + + Link this device to an existing account + Połącz to urządzenie z istniejącym kontem + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Ubuntu'; font-size:14px; color:#555555;">To link this device to another account, you first </span><span style=" font-family:'Ubuntu'; font-size:14px; font-weight:600; color:#555555;">need to obtain a PIN</span><span style=" font-family:'Ubuntu'; font-size:14px; color:#555555;"> code. To generate the PIN code:</span></p> +<ol style="margin-top: 0px; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; -qt-list-indent: 1;"><li style=" font-family:'Ubuntu'; font-size:14px; color:#555555;" style=" margin-top:12px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:14px;">Go to the </span><span style=" font-size:14px; font-weight:600;">Account management setting</span><span style=" font-size:14px;"> of a previous device</span></li> +<li style=" font-family:'Ubuntu'; font-size:14px; color:#555555;" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:14px;">Choose the </span><span style=" font-size:14px; font-weight:600;">Jami account</span><span style=" font-size:14px;"> you want to use</span></li> +<li style=" font-family:'Ubuntu'; font-size:14px; color:#555555;" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:14px;">Go to the </span><span style=" font-size:14px; font-weight:600;">Devices</span><span style=" font-size:14px;"> tab</span></li> +<li style=" font-family:'Ubuntu'; font-size:14px; color:#555555;" style=" margin-top:0px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:14px;">Select </span><span style=" font-size:14px; font-weight:600;">Add a device</span></li></ol> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Ubuntu'; font-size:14px; color:#555555;">You will get the necessary PIN to complete this form. The PIN is only valid for </span><span style=" font-family:'Ubuntu'; font-size:14px; font-weight:600; color:#555555;">10 minutes</span><span style=" font-family:'Ubuntu'; font-size:10px; color:#555555;">.</span></p></body></html> + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Ubuntu'; font-size:14px; color:#555555;">Aby połączyć to urządzenie z innym kątem, najpierw</span><span style=" font-family:'Ubuntu'; font-size:14px; font-weight:600; color:#555555;">musisz pozyskać kod PIN</span><span style=" font-family:'Ubuntu'; font-size:14px; color:#555555;"> Aby wygenerować kod PIN:</span></p> +<ol style="margin-top: 0px; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; -qt-list-indent: 1;"><li style=" font-family:'Ubuntu'; font-size:14px; color:#555555;" style=" margin-top:12px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:14px;">Przejdź do </span><span style=" font-size:14px; font-weight:600;">Ustawień zarządzenia kontem</span><span style=" font-size:14px;"> na poprzednim urządzeniu</span></li> +<li style=" font-family:'Ubuntu'; font-size:14px; color:#555555;" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:14px;">Wybierz </span><span style=" font-size:14px; font-weight:600;">Konto Jami,</span><span style=" font-size:14px;"> z którego chcesz korzystać</span></li> +<li style=" font-family:'Ubuntu'; font-size:14px; color:#555555;" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:14px;">Przejdź do</span><span style=" font-size:14px; font-weight:600;">Karty urządzeń</span></li> +<li style=" font-family:'Ubuntu'; font-size:14px; color:#555555;" style=" margin-top:0px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:14px;">Zaznacz </span><span style=" font-size:14px; font-weight:600;">Dodaj urządzenie</span></li></ol> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Ubuntu'; font-size:14px; color:#555555;">Będziesz potrzebować kodu PIN, aby uzupełnić ten formularz. Kod PIN jest ważny przez</span><span style=" font-family:'Ubuntu'; font-size:14px; font-weight:600; color:#555555;">10 minut</span><span style=" font-family:'Ubuntu'; font-size:10px; color:#555555;">.</span></p></body></html> + + + + Enter your pin: + Wpisz swój PIN: + + + + Or import a file: + Lub zaimportuj plik: + + + + Link from exported account archive file + Połącz z wyeksportowanego pliku archiwum + + + + + + (None) + (Brak) + + + + Password: + Hasło: + + + + + Profile + Profil + + + + + Profile name + Nazwa profilu + + + + Account + Konto + + + + Register your username. +This will reserve the username so that only you can use it. +Your friends will be able to call you with your usename +instead of using your ID. + Zarejestruj swoją nazwę użytkownika. +Ta akcja zarezerwuje nazwę użytkownika, tak, że tylko ty będziesz w stanie z niej korzystać. +Twoi znajomi będą w stanie kontaktować się za pomocą tej nazwy użytkownika zamiast używać twojego ID. + + + + Public username checkbox + Checkbox publicznej nazwy użytkownika + + + + Checkbox selecting if the user wants a public username + Checkbox zaznaczający, jeśli użytkownik chce mieć publiczną nazwę użytkownika + + + + Register public username + Zarejestruj publiczną nazwę użytkownika + + + + Public username edit + Edycja publicznej nazwy użytkownika + + + + Choose your username + Wybierz swoją nazwę użytkownika + + + + Password text input + Pole tekstowe hasła + + + + Password text entry + Wpis tekstu hasła + + + + + Password + Hasło + + + + + Password confirmation text input + Pole potwierdzenia hasła + + + + Confirm password + Potwierdź hasło + + + + SIP Account + Konto SIP + + + + SIP Server edit + Edycja Serwera SIP + + + + Server + Serwer + + + + SIP proxy input + Pole wprowadzenia proxy dla SIP + + + + SIP proxy text entry + + + + + Proxy + Pełnomocnik + + + + SIP username input + Wprowadź nazwę użytkownika SIP + + + + SIP Password text entry + + + + + Username + Nazwa użytkownika + + + + + SIP Password text input + + + + + Generating your Jami account… + Tworzenie konta Jami... + + + + Previous page button + Guzik poprzedniej strony + + + + push button to access previous page of wizard + guzik dostępu do poprzedniej strony instalatora + + + + Previous + Poprzednie + + + + Cancel account create/link + Anuluj konto stwórz/połącz + + + + push button to cancel account creation or linking + guzik do anulowania tworzenia lub łączenia konta + + + + Back + Wstecz + + + + Next page Button + Guzik następnej strony + + + + Push button to access next page of wizard + Guzik dostępu do następnej strony instalatora + + + + Next + Następne + + + + Open File + Otwórz plik + + + + Jami archive files (*.gz); All files (*) + Pliki archiwum Jami (*.gz); Wszystkie pliki (*) + + + + Your account needs to be migrated. Enter your password. + Twoje konto musi zostać zaktualizowane. Wprowadź swoje hasło. + + + + Migrating your Jami account... + Migrowanie twojego kąta Jami... + + + + Importing account archive... + Importowanie archiwum konta... + + + + Generating your Jami account... + Generowanie twojego konta Jami... + + + + Generating your SIP account... + + + + + Error creating account + Błąd podczas tworzenia konta + + + + PasswordDialog + + + Change Account Password + Zmień Hasło Konta + + + + Enter Current Password + Wprowadź Obecne Hasło + + + + Enter New Password + Wprowadź Nowe Hasło + + + + Confirm New Password + Potwierdź Nowe Hasło + + + + Confirm + Potwierdź + + + + Cancel + Anuluj + + + + Current Password Incorrect + Bieżące Hasło Jest Niepoprawne + + + + PhotoBoothDialog + + + Photobooth + Budka fotograficzna + + + + PhotoboothWidget + + + Form + Forma + + + + Photobooth display + Widok z przodu + + + + Choose File + Wybierz Plik + + + + Image Files (*.jpg *.jpeg *.png) + Pliki Obrazków (*.jpg *.jpeg *.png) + + + + PrivateBridging + + + Choose File + Wybierz Plik + + + + Files (*) + Pliki (*) + + + + QObject + + + No default mail client found + Nie znaleziono domyślnego klienta poczty + + + + + Edit Device Name + Edytuj Nazwę Urządzenia + + + + Unlink Device From Account + Odłącz Urządzenie Od Konta + + + + Save new device name + + + + + Add as contact + + + + + RingButton + + + Select folder + Wybierz folder + + + + SettingsWidget + + + Form + Forma + + + + Settings + Ustawienia + + + + Account + Konto + + + + + General + Generalne + + + + + Audio / Video + Audio / Wideo + + + + System + System + + + + Enable desktop notifications + Zezwól na powiadomienia na pulpicie + + + + Keep minimized on close + Przechowaj zminimalizowane przy zamknięciu + + + + Download folder + Folder pobrane + + + + Save in + Zapisz w + + + + Always Recording + Zawsze Nagrywaj + + + + Updates + Aktualizacje + + + + Check for updates automatically every + Sprawdzaj automatycznie aktualizacje co + + + + Interval between update checks in days selector + Pole wyboru interwału pomiędzy sprawdzaniem aktualizacji w dniach + + + + days + dni + + + + Check for updates now button + Guzik sprawdzenia aktualizacji teraz + + + + Check for updates now + Sprawdź aktualizacje teraz + + + + Password + Hasło + + + + + Enable + Włącz + + + + toggle enable notifications + + + + + Toggle keep minimized on close + + + + + Call Recordings + + + + + Toggle automatic updates + + + + + Jami Account + + + + + + Profile + Profil + + + + + Identity + Tożsamość + + + + Id + Id + + + + Registered name + Zarejestrowana nazwa + + + + Type here to register a username + Wpisz tutaj, by zarejestrować nazwę użytkownika + + + + Register + Zarejestruj + + + + Change Password + Zmień Hasło + + + + Export Account + Wyeksportuj konto + + + + + Delete Account + Usuń Konto + + + + Linked Devices + Połączone Urządzenia + + + + Link Another Device + Połącz Inne Urządzenie + + + + Banned Contacts + Zablokowane Kontakty + + + + Format + + + + + Video device framerate selector + + + + + Preview unavailable + + + + + + Advanced Account Settings + Zaawansowane Ustawienia Konta + + + + SIP Account + Konto SIP + + + + Username + Nazwa użytkownika + + + + Hostname + Nazwa hosta + + + + Proxy + Pełnomocnik + + + + Audio + Audio + + + + Microphone + Mikrofon + + + + Audio input device selector + Pole wyboru urządzenia wejściowego audio + + + + Output Device + Urządzenie Wyjściowe + + + + Choose the output device + Wybierz urządzenie wyjściowe + + + + Video + Wideo + + + + Device + Urządzenie + + + + Video device selector + Pole wyboru urządzenia wideo + + + + A registered name should not have any spaces and must be at least three letters long + Zarejestrowana nazwa powinna nie zawierać żadnych spacji i musi mieć przynajmniej 3 litery długości + + + + This name is already taken + Ta nazwa jest już zajęta + + + + + Enter an alias + + + + + Register this name + Zarejestruj tą nazwę + + + + Remove Device + Usuń Urządzenie + + + + Enter this account's password to confirm the removal of this device + Wprowadź hasło do tego konta, aby potwierdzić usunięcie tego urządzenia + + + + Are you sure you wish to remove this device? + + + + + Export Account Here + Wyeksportuj Konto Tutaj + + + + Select A Folder For Your Downloads + Wybierz Folder Dla Twoich Pobranych + + + + Select A Folder For Your Recordings + Wybierz Folder Dla Twoich Nagrań + + + + VideoOverlay + + + Call on Hold + Rozmowa jest Zawieszona + + + + Hold / Unhold + Zawiesić / Wznowić + + + + Chat + Czat + + + + Mute Mic + Wyłącz mikrofon + + + + Record call + Nagraj Rozmowę + + + + Name label + Etykieta Nazwiska + + + + Time elapsed + Czas się skończył + + + + 00:00 + 00:00 + + + + Hangup + Odłożyć słuchawkę + + + + Mute Video + Wyłącz video + + + + VideoView + + + Share entire screen + Podziel się obszarem ekranu + + + + Share screen area + Podziel się obszar ekranu + + + + Share file + Podziel się plikiem + + + \ No newline at end of file diff --git a/translations/ring_client_windows_pl_PL.ts b/translations/ring_client_windows_pl_PL.ts new file mode 100644 index 00000000..9bcf83e4 --- /dev/null +++ b/translations/ring_client_windows_pl_PL.ts @@ -0,0 +1,1590 @@ + + + AboutDialog + + + + About + O programie + + + + about button + przycisk o programie + + + + credits button + przycisk zasługi + + + + Credits + Podziękowania + + + + Free as in Freedom + + + + + The Microsoft Windows client for Jami. +Jami is a secured and distributed communication software. + Klient Jami dla Microsoft Windows. +Jami jest wolnym oprogramowaniem do uniwersalnej komunikacji, respektującym wolność i prywatność swoich użytkowników. + + + + version + Wersja + + + + Created by: + Stworzone przez: + + + + Artwork by: + Obrazki przez: + + + + Based on the SFLPhone project + Na podstawie projektu SFLPhone + + + + AccountItemDelegate + + + Add Account + Dodaj konto + + + + AdvancedSIPSettingsWidget + + + Form + Forma + + + + Call Settings + + + + + Auto Answer Calls + + + + + Enable Custom Ringtone + + + + + Connectivity + Łączność + + + + STUN Address + + + + + Use STUN + Użyj STUN + + + + Use UPnP + + + + + Use TURN + Użyj TURN + + + + TURN Password + + + + + TURN Username + + + + + TURN Address + + + + + Media + Multimedia + + + + Enable Video + Włącz video + + + + Video Codecs + + + + + Audio Codecs + Kodeki audio + + + + Audio Files (*.wav *.ogg *.opus *.mp3 *aiff *wma) + + + + + Add a custom ringtone + + + + + AdvancedSettingsWidget + + + Form + Forma + + + + Call Settings + + + + + Allow Calls From Untrusted Peers + + + + + Auto Answer Calls + + + + + Enable Custom Ringtone + + + + + Add a custom ringtone + + + + + Name Server + Serwer nazw + + + + Address + Adres + + + + OpenDHT Configuration + + + + + Enable Proxy + + + + + Bootstrap + Bootstrap + + + + Security + Zabezpieczenia + + + + Private Key Password + Hasło Klucza Prywatnego + + + + User Certificate + Certyfikat Użytkownika + + + + Private Key + Klucz Prywatny + + + + CA Certificate + + + + + Connectivity + Łączność + + + + Use STUN + Użyj STUN + + + + STUN Address + + + + + Use UPnP + + + + + Use TURN + Użyj TURN + + + + TURN Password + + + + + TURN Username + + + + + TURN Address + + + + + Media + Multimedia + + + + Enable Video + Włącz video + + + + Audio Codecs + Kodeki audio + + + + Video Codecs + + + + + Audio Files (*.wav *.ogg *.opus *.mp3 *aiff *wma) + + + + + AnimatedOverlay + + + Form + Forma + + + + BannedItemWidget + + + Form + Forma + + + + name + + + + + id + + + + + CallWidget + + + Show conversations + Pokaż rozmowy + + + + Conversations + Rozmowy + + + + Search contact text input + + + + + Jami is free software for universal communication which respects the freedoms and privacy of its users. + Jami jest wolnym oprogramowaniem do uniwersalnej komunikacji, respektującym wolności i prywatność swoich użytkowników. + + + + + This is your ID. +Copy and share it with your friends! + + + + + + Show ring ID QR code + Rozpocznij połączenie wideo + + + + Share ring ID button + + + + + Double-click to copy + + + + + Error while generating QR Code + Wystąpił błąd podczas generowania kodu QR. + + + + + best name + + + + + best Id + + + + + Back to homepage button + + + + + Add to contacts + Dodaj do kontaków + + + + Show invites + Pokaż zaproszenia + + + + Invites + Zaproszenia + + + + + Find a new or existing contact + + + + + Wants to talk to you! + Chce z tobą rozmawiać! + + + + Answer incoming call button + + + + + Ignore incoming call button + + + + + Answer + Odbierz + + + + Ignore + Zignoruj + + + + Cancel outgoing call + Anuluj wychodzące połączenie + + + + Cancel + Anuluj + + + + Start video call + Rozpocznij rozmowę wideo + + + + Start audio call + Rozpocznij połączenie głosowe + + + + Clear conversation + Wyczyść rozmowę + + + + Remove contact + Usuń kontakt + + + + Block contact + Blokuj kontakt + + + + Copy number + Skopiuj numer + + + + Search your received invitations + + + + + Contact me on Jami + + + + + My Id is : + + + + + %1 + %1 is the contact username + %1 + + + + %1 + %1 is the contact unique identifier + %1 + + + + Call incoming from %1 + Połączenie przychodzące od %1 + + + + DeleteAccountDialog + + + Account deletion + + + + + Do you really want to delete the following account? + + + + + If this account hasn't been exported, or added to another device, it will be irrevocably lost. + + + + + Permanently delete account + + + + + Delete + Usuń + + + + Cancel account deletion + + + + + Cancel + Anuluj + + + + DeviceItemWidget + + + Form + Forma + + + + Device Id + + + + + this device + to urządzenie + + + + InviteButtonsWidget + + + Accept + Akceptuj + + + + Refuse + Odmów + + + + Block + Blokuj + + + + LinkDeviceDialog + + + Dialog + + + + + Enter your account password + + + + + Password + Hasło + + + + Ok + Ok + + + + Cancel + Anuluj + + + + Exporting account + + + + + Your PIN is + + + + + PIN + PIN + + + + This pin and the account password should be entered in your device within 10 minutes. + + + + + Close + Zamknij + + + + Link Another Device + + + + + Incorrect password + Nieprawidłowe hasło + + + + Something went wrong. +Please try again later. + + + + + MainWindow + + + Settings + Ustawienia + + + + Exit + Wyjdź + + + + About + O + + + + Jami + Jami + + + + NameRegistrationDialog + + + Set Registered Name + + + + + Enter your account password + + + + + Password text input + + + + + Password text entry + + + + + Password + Hasło + + + + Register + Zarejestruj + + + + Cancel + Anuluj + + + + Registering Name + + + + + Something went wrong + + + + + Close + Zamknij + + + + Incorrect password + Nieprawidłowe hasło + + + + Network error + Błąd sieci + + + + NewWizardWidget + + + Form + Forma + + + + Welcome Label + + + + + Welcome to + + + + + Welcome Logo + + + + + Create Jami account button + + + + + Push button for Jami account creation start trigger + + + + + Create a Jami account + Utwórz konto Jami + + + + Link device button + + + + + Push button for device linkage start trigger + + + + + Link this device to an account + Połącz to urządzenie z kontem + + + + Create Jami SIP account button + + + + + Push button for Jami SIP account creation start trigger + + + + + Create a SIP account + + + + + Link this device to an existing account + Połącz to urządzenie z istniejącym kontem + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Ubuntu'; font-size:14px; color:#555555;">To link this device to another account, you first </span><span style=" font-family:'Ubuntu'; font-size:14px; font-weight:600; color:#555555;">need to obtain a PIN</span><span style=" font-family:'Ubuntu'; font-size:14px; color:#555555;"> code. To generate the PIN code:</span></p> +<ol style="margin-top: 0px; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; -qt-list-indent: 1;"><li style=" font-family:'Ubuntu'; font-size:14px; color:#555555;" style=" margin-top:12px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:14px;">Go to the </span><span style=" font-size:14px; font-weight:600;">Account management setting</span><span style=" font-size:14px;"> of a previous device</span></li> +<li style=" font-family:'Ubuntu'; font-size:14px; color:#555555;" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:14px;">Choose the </span><span style=" font-size:14px; font-weight:600;">Jami account</span><span style=" font-size:14px;"> you want to use</span></li> +<li style=" font-family:'Ubuntu'; font-size:14px; color:#555555;" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:14px;">Go to the </span><span style=" font-size:14px; font-weight:600;">Devices</span><span style=" font-size:14px;"> tab</span></li> +<li style=" font-family:'Ubuntu'; font-size:14px; color:#555555;" style=" margin-top:0px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:14px;">Select </span><span style=" font-size:14px; font-weight:600;">Add a device</span></li></ol> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Ubuntu'; font-size:14px; color:#555555;">You will get the necessary PIN to complete this form. The PIN is only valid for </span><span style=" font-family:'Ubuntu'; font-size:14px; font-weight:600; color:#555555;">10 minutes</span><span style=" font-family:'Ubuntu'; font-size:10px; color:#555555;">.</span></p></body></html> + + + + + Enter your pin: + Wpisz swój PIN: + + + + Or import a file: + Lub zaimportuj plik: + + + + Link from exported account archive file + + + + + + + (None) + + + + + Password: + Hasło: + + + + + Profile + Profil + + + + + Profile name + Nazwa profilu + + + + Account + Konto + + + + Register your username. +This will reserve the username so that only you can use it. +Your friends will be able to call you with your usename +instead of using your ID. + + + + + Public username checkbox + + + + + Checkbox selecting if the user wants a public username + + + + + Register public username + Zarejestruj publiczną nazwę użytkownika + + + + Public username edit + + + + + Choose your username + Wybierz swoją nazwę użytkownika + + + + Password text input + + + + + Password text entry + + + + + + Password + Hasło + + + + + Password confirmation text input + Pole potwierdzenia hasła + + + + Confirm password + Potwierdź hasło + + + + SIP Account + Konto SIP + + + + SIP Server edit + + + + + Server + + + + + SIP proxy input + + + + + SIP proxy text entry + + + + + Proxy + Pełnomocnik + + + + SIP username input + Wprowadź nazwę użytkownika SIP + + + + SIP Password text entry + + + + + Username + Nazwa użytkownika + + + + + SIP Password text input + + + + + Generating your Jami account… + Tworzenie konta Jami... + + + + Previous page button + + + + + push button to access previous page of wizard + + + + + Previous + Poprzednie + + + + Cancel account create/link + + + + + push button to cancel account creation or linking + + + + + Back + Wstecz + + + + Next page Button + + + + + Push button to access next page of wizard + + + + + Next + Następne + + + + Open File + Otwórz plik + + + + Jami archive files (*.gz); All files (*) + + + + + Your account needs to be migrated. Enter your password. + + + + + Migrating your Jami account... + + + + + Importing account archive... + + + + + Generating your Jami account... + + + + + Generating your SIP account... + + + + + Error creating account + + + + + PasswordDialog + + + Change Account Password + + + + + Enter Current Password + + + + + Enter New Password + + + + + Confirm New Password + + + + + Confirm + + + + + Cancel + Anuluj + + + + Current Password Incorrect + + + + + PhotoBoothDialog + + + Photobooth + Budka fotograficzna + + + + PhotoboothWidget + + + Form + Forma + + + + Photobooth display + + + + + Choose File + Wybierz Plik + + + + Image Files (*.jpg *.jpeg *.png) + + + + + PrivateBridging + + + Choose File + Wybierz Plik + + + + Files (*) + Pliki (*) + + + + QObject + + + No default mail client found + Nie znaleziono domyślnego klienta poczty + + + + + Edit Device Name + + + + + Unlink Device From Account + + + + + Save new device name + + + + + Add as contact + + + + + RingButton + + + Select folder + Wybierz folder + + + + SettingsWidget + + + Form + Forma + + + + Settings + Ustawienia + + + + Account + Konto + + + + + General + Generalne + + + + + Audio / Video + + + + + System + System + + + + Enable desktop notifications + + + + + Keep minimized on close + + + + + Download folder + + + + + Save in + Zapisz w + + + + Always Recording + + + + + Updates + Aktualizacje + + + + Check for updates automatically every + + + + + Interval between update checks in days selector + + + + + days + + + + + Check for updates now button + + + + + Check for updates now + + + + + Password + Hasło + + + + + Enable + + + + + toggle enable notifications + + + + + Toggle keep minimized on close + + + + + Call Recordings + + + + + Toggle automatic updates + + + + + Jami Account + + + + + + Profile + Profil + + + + + Identity + Tożsamość + + + + Id + + + + + Registered name + Zarejestrowana nazwa + + + + Type here to register a username + + + + + Register + Zarejestruj + + + + Change Password + + + + + Export Account + + + + + + Delete Account + Usuń konto + + + + Linked Devices + + + + + Link Another Device + + + + + Banned Contacts + + + + + Format + + + + + Video device framerate selector + + + + + Preview unavailable + + + + + + Advanced Account Settings + + + + + SIP Account + Konto SIP + + + + Username + Nazwa użytkownika + + + + Hostname + Nazwa hosta + + + + Proxy + Pełnomocnik + + + + Audio + Audio + + + + Microphone + + + + + Audio input device selector + + + + + Output Device + Urządzenie wyjściowe + + + + Choose the output device + + + + + Video + Wideo + + + + Device + Urządzenie + + + + Video device selector + + + + + A registered name should not have any spaces and must be at least three letters long + + + + + This name is already taken + + + + + + Enter an alias + + + + + Register this name + + + + + Remove Device + + + + + Enter this account's password to confirm the removal of this device + + + + + Are you sure you wish to remove this device? + + + + + Export Account Here + + + + + Select A Folder For Your Downloads + + + + + Select A Folder For Your Recordings + + + + + VideoOverlay + + + Call on Hold + Rozmowa jest Zawieszona + + + + Hold / Unhold + Zawiesić / Wznowić + + + + Chat + Czat + + + + Mute Mic + Wyłącz mikrofon + + + + Record call + Nagraj rozmowę + + + + Name label + Etykieta Nazwiska + + + + Time elapsed + Czas się skończył + + + + 00:00 + 00:00 + + + + Hangup + Odłożyć słuchawkę + + + + Mute Video + Wyłącz video + + + + VideoView + + + Share entire screen + Podziel się obszarem ekranu + + + + Share screen area + Podziel się obszar ekranu + + + + Share file + Podziel się plikiem + + + \ No newline at end of file diff --git a/translations/ring_client_windows_pt.ts b/translations/ring_client_windows_pt.ts new file mode 100644 index 00000000..bd851d17 --- /dev/null +++ b/translations/ring_client_windows_pt.ts @@ -0,0 +1,1606 @@ + + + AboutDialog + + + + About + Sobre + + + + about button + botão sobre + + + + credits button + botão créditos + + + + Credits + Créditos + + + + Free as in Freedom + + + + + The Microsoft Windows client for Jami. +Jami is a secured and distributed communication software. + O cliente Microsoft Windows para o Jami +O Jami é um programa de comunicação distribuído e seguro. + + + + version + versão + + + + Created by: + Criado por: + + + + Artwork by: + Arte por: + + + + Based on the SFLPhone project + Baseado no projeto SFLPhone + + + + AccountItemDelegate + + + Add Account + Adicionar Conta + + + + AdvancedSIPSettingsWidget + + + Form + Formulário + + + + Call Settings + Configurações de chamadas + + + + Auto Answer Calls + Atender chamadas automaticamente + + + + Enable Custom Ringtone + Ativar toque de chamada personalizado + + + + Connectivity + Conectividade + + + + STUN Address + Endereço STUN + + + + Use STUN + Usar STUN + + + + Use UPnP + Usar UPnP + + + + Use TURN + Usar TURN + + + + TURN Password + Palavra-chave TURN + + + + TURN Username + Nome de utilizador TURN + + + + TURN Address + Endereço TURN + + + + Media + Média + + + + Enable Video + Ativar Vídeo + + + + Video Codecs + Codecs de vídeo + + + + Audio Codecs + Codecs de áudio + + + + Audio Files (*.wav *.ogg *.opus *.mp3 *aiff *wma) + Ficheiros de áudio (*.wav *.ogg *.opus *.mp3 *aiff *wma) + + + + Add a custom ringtone + Adicionar um toque de chamada personalizado + + + + AdvancedSettingsWidget + + + Form + Formulário + + + + Call Settings + Configurações de chamadas + + + + Allow Calls From Untrusted Peers + Permitir chamadas de utilizadores desconhecidos + + + + Auto Answer Calls + Atender chamadas automaticamente + + + + Enable Custom Ringtone + Ativar toque de chamada personalizado + + + + Add a custom ringtone + Adicionar um toque de chamada personalizado + + + + Name Server + Nome do servidor + + + + Address + Endereço + + + + OpenDHT Configuration + Configuração OpenDHT + + + + Enable Proxy + Ativar Proxy + + + + Bootstrap + Inicialização + + + + Security + Segurança + + + + Private Key Password + Palavra-chave da Chave Privada + + + + User Certificate + Certificado do Utilizador + + + + Private Key + Chave privada + + + + CA Certificate + Certificado CA + + + + Connectivity + Conectividade + + + + Use STUN + Usar STUN + + + + STUN Address + Endereço STUN + + + + Use UPnP + Usar UPnP + + + + Use TURN + Usar TURN + + + + TURN Password + Palavra-chave TURN + + + + TURN Username + Nome de utilizador TURN + + + + TURN Address + Endereço TURN + + + + Media + Média + + + + Enable Video + Ativar Vídeo + + + + Audio Codecs + Codecs de áudio + + + + Video Codecs + Codecs de vídeo + + + + Audio Files (*.wav *.ogg *.opus *.mp3 *aiff *wma) + Ficheiros de áudio (*.wav *.ogg *.opus *.mp3 *aiff *wma) + + + + AnimatedOverlay + + + Form + Formulário + + + + BannedItemWidget + + + Form + Formulário + + + + name + nome + + + + id + id + + + + CallWidget + + + Show conversations + Ver conversações + + + + Conversations + Conversas + + + + Search contact text input + Entrada de texto para pesquisa de contacto + + + + Jami is free software for universal communication which respects the freedoms and privacy of its users. + O Jami é um programa livre para comunicação universal que respeita as liberdades e privacidade dos seus utilizadores. + + + + + This is your ID. +Copy and share it with your friends! + + + Este é o seu ID. +Copie-o e partilhe-o com os seus amigos! + + + + + Show ring ID QR code + Mostrar código QR do seu ID do Ring + + + + Share ring ID button + Botão para partilhar o seu ID do Ring + + + + Double-click to copy + Duplo-clique para copiar + + + + Error while generating QR Code + Erro ao gerar o Código QR + + + + + best name + melhor nome + + + + best Id + melhor Id + + + + Back to homepage button + Botão para voltar à página inicial + + + + Add to contacts + Adicionar aos contactos + + + + Show invites + Mostrar convites + + + + Invites + Convites + + + + + Find a new or existing contact + Procurar um contacto novo ou existente + + + + Wants to talk to you! + Quer conversar consigo! + + + + Answer incoming call button + Botão para atender chamada + + + + Ignore incoming call button + Botão para ignorar chamada + + + + Answer + Resposta + + + + Ignore + Ignorar + + + + Cancel outgoing call + Cancelar chamada efetuada + + + + Cancel + Cancelar + + + + Start video call + Começar chamada de vídeo + + + + Start audio call + Começar chamada de áudio + + + + Clear conversation + Limpar conversação + + + + Remove contact + Remover contacto + + + + Block contact + Bloquear contacto + + + + Copy number + Copiar número + + + + Search your received invitations + Pesquisar os seus convites recebidos + + + + Contact me on Jami + Contacte-me no Jami + + + + My Id is : + O meu ID é: + + + + %1 + %1 is the contact username + %1 + + + + %1 + %1 is the contact unique identifier + %1 + + + + Call incoming from %1 + A receber chamada de %1 + + + + DeleteAccountDialog + + + Account deletion + Eliminação de conta + + + + Do you really want to delete the following account? + Tem certeza que quer eliminar a seguinte conta? + + + + If this account hasn't been exported, or added to another device, it will be irrevocably lost. + Se esta conta não foi exportada ou adicionada a outro dispositivo, ela será perdida. + + + + Permanently delete account + Eliminar conta permanentemente + + + + Delete + Eliminar + + + + Cancel account deletion + Cancelar eliminação da conta + + + + Cancel + Cancelar + + + + DeviceItemWidget + + + Form + Formulário + + + + Device Id + ID do dispositivo + + + + this device + este dispositivo + + + + InviteButtonsWidget + + + Accept + Aceitar + + + + Refuse + Recusar + + + + Block + Bloquear + + + + LinkDeviceDialog + + + Dialog + Diálogo + + + + Enter your account password + Introduza a palavra-chave da sua conta + + + + Password + Palavra-chave + + + + Ok + OK + + + + Cancel + Cancelar + + + + Exporting account + Exportar a conta + + + + Your PIN is + O seu PIN é + + + + PIN + PIN + + + + This pin and the account password should be entered in your device within 10 minutes. + Este PIN e a palavra-chave devem ser inseridos no seu novo dispositivo nos próximos 10 minutos. + + + + Close + Fechar + + + + Link Another Device + Associar outro dispositivo + + + + Incorrect password + Palavra-chave incorreta + + + + Something went wrong. +Please try again later. + Algo correu mal. +Por favor tente de novo mais tarde. + + + + MainWindow + + + Settings + Configurações + + + + Exit + Sair + + + + About + Sobre + + + + Jami + Jami + + + + NameRegistrationDialog + + + Set Registered Name + Definir o nome registado + + + + Enter your account password + Introduza a palavra-chave da sua conta + + + + Password text input + Entrada de texto da palavra-chave + + + + Password text entry + Campo de texto da palavra-chave + + + + Password + Palavra-chave + + + + Register + Registar + + + + Cancel + Cancelar + + + + Registering Name + Registar o nome + + + + Something went wrong + Algo correu mal + + + + Close + Fechar + + + + Incorrect password + Palavra-chave incorreta + + + + Network error + Erro de rede + + + + NewWizardWidget + + + Form + Formulário + + + + Welcome Label + Rótulo de Boas-Vindas + + + + Welcome to + Bem-vindo(a) ao + + + + Welcome Logo + Logótipo de Boas-Vindas + + + + Create Jami account button + Botão para criar conta Jami + + + + Push button for Jami account creation start trigger + Botão para acionar a criação da conta do Jami + + + + Create a Jami account + Criar uma conta Jami + + + + Link device button + Botão para associar dispositivo + + + + Push button for device linkage start trigger + Botão para acionar a associação de dispositivo + + + + Link this device to an account + Associar este dispositivo a uma conta + + + + Create Jami SIP account button + Botão para criar a conta SIP Jami + + + + Push button for Jami SIP account creation start trigger + Botão para acionar a criação da conta SIP Jami + + + + Create a SIP account + Criar uma conta SIP + + + + Link this device to an existing account + Associar este dispositivo a uma conta existente + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Ubuntu'; font-size:14px; color:#555555;">To link this device to another account, you first </span><span style=" font-family:'Ubuntu'; font-size:14px; font-weight:600; color:#555555;">need to obtain a PIN</span><span style=" font-family:'Ubuntu'; font-size:14px; color:#555555;"> code. To generate the PIN code:</span></p> +<ol style="margin-top: 0px; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; -qt-list-indent: 1;"><li style=" font-family:'Ubuntu'; font-size:14px; color:#555555;" style=" margin-top:12px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:14px;">Go to the </span><span style=" font-size:14px; font-weight:600;">Account management setting</span><span style=" font-size:14px;"> of a previous device</span></li> +<li style=" font-family:'Ubuntu'; font-size:14px; color:#555555;" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:14px;">Choose the </span><span style=" font-size:14px; font-weight:600;">Jami account</span><span style=" font-size:14px;"> you want to use</span></li> +<li style=" font-family:'Ubuntu'; font-size:14px; color:#555555;" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:14px;">Go to the </span><span style=" font-size:14px; font-weight:600;">Devices</span><span style=" font-size:14px;"> tab</span></li> +<li style=" font-family:'Ubuntu'; font-size:14px; color:#555555;" style=" margin-top:0px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:14px;">Select </span><span style=" font-size:14px; font-weight:600;">Add a device</span></li></ol> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Ubuntu'; font-size:14px; color:#555555;">You will get the necessary PIN to complete this form. The PIN is only valid for </span><span style=" font-family:'Ubuntu'; font-size:14px; font-weight:600; color:#555555;">10 minutes</span><span style=" font-family:'Ubuntu'; font-size:10px; color:#555555;">.</span></p></body></html> + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Ubuntu'; font-size:14px; color:#555555;">Para associar este dispositivo a outra conta, primeiro </span><span style=" font-family:'Ubuntu'; font-size:14px; font-weight:600; color:#555555;">tem de obter um código PIN.</span><span style=" font-family:'Ubuntu'; font-size:14px; color:#555555;">Para gerar o código PIN:</span></p> +<ol style="margin-top: 0px; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; -qt-list-indent: 1;"><li style=" font-family:'Ubuntu'; font-size:14px; color:#555555;" style=" margin-top:12px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:14px;">Aceda à </span><span style=" font-size:14px; font-weight:600;">configuração de gestão de conta</span><span style=" font-size:14px;"> de um dispositivo anterior</span></li> +<li style=" font-family:'Ubuntu'; font-size:14px; color:#555555;" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:14px;">Escolha a </span><span style=" font-size:14px; font-weight:600;">conta Jami</span><span style=" font-size:14px;"> quer quer usar</span></li> +<li style=" font-family:'Ubuntu'; font-size:14px; color:#555555;" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:14px;">Aceda à aba </span><span style=" font-size:14px; font-weight:600;">Dispositivos</span><span style=" font-size:14px;"> </span></li> +<li style=" font-family:'Ubuntu'; font-size:14px; color:#555555;" style=" margin-top:0px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:14px;">Selecione </span><span style=" font-size:14px; font-weight:600;">Adicionar dispositivo</span></li></ol> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Ubuntu'; font-size:14px; color:#555555;">Irá obter o PIN necessário para completar este formulário. O código PIN é válido apenas durante </span><span style=" font-family:'Ubuntu'; font-size:14px; font-weight:600; color:#555555;">10 minutos</span><span style=" font-family:'Ubuntu'; font-size:10px; color:#555555;">.</span></p></body></html> + + + + Enter your pin: + Introduza o seu PIN: + + + + Or import a file: + Ou importe de um ficheiro: + + + + Link from exported account archive file + Link do ficheiro da conta exportada + + + + + + (None) + (nenhum) + + + + Password: + Palavra-chave: + + + + + Profile + Perfil + + + + + Profile name + Nome do perfil + + + + Account + Conta + + + + Register your username. +This will reserve the username so that only you can use it. +Your friends will be able to call you with your usename +instead of using your ID. + Registe o seu nome de utilizador. +Isto irá reservar o nome de utilizador para que apenas você o possa utilizar. +Os seus amigos serão capazes de contactá-lo com seu nome de +utilizador em vez do seu ID. + + + + Public username checkbox + Caixa de visto para o nome público de utilizador + + + + Checkbox selecting if the user wants a public username + Caixa de visto para indicar se o utilizador quer um nome público de utilizador + + + + Register public username + Registar nome de utilizador público + + + + Public username edit + Editar nome público de utilizador + + + + Choose your username + Escolha o seu nome de utilizador + + + + Password text input + Entrada de texto da palavra-chave + + + + Password text entry + Campo de texto da palavra-chave + + + + + Password + Palavra-chave + + + + + Password confirmation text input + Campo de texto para confirmação da palavra-chave + + + + Confirm password + Confirmar palavra-chave + + + + SIP Account + Conta SIP + + + + SIP Server edit + Editar servidor SIP + + + + Server + Servidor + + + + SIP proxy input + Entrada do proxy SIP + + + + SIP proxy text entry + Campo de texto do proxy SIP + + + + Proxy + Proxy + + + + SIP username input + Entrada de nome de utilizador SIP + + + + SIP Password text entry + Campo de texto da palavra-chave SIP + + + + Username + Nome de utilizador + + + + + SIP Password text input + Entrada de texto da palavra-chave SIP + + + + Generating your Jami account… + A gerar a sua conta Jami... + + + + Previous page button + Botão de página anterior + + + + push button to access previous page of wizard + Botão de pressionar para aceder à página anterior do assistente + + + + Previous + Anterior + + + + Cancel account create/link + Cancelar a criação de conta / associação + + + + push button to cancel account creation or linking + botão para cancelar criação de conta ou associação + + + + Back + Voltar + + + + Next page Button + Botão de página seguinte + + + + Push button to access next page of wizard + Botão de pressionar para aceder à página seguinte do assistente + + + + Next + Próximo + + + + Open File + Abrir Ficheiro + + + + Jami archive files (*.gz); All files (*) + Ficheiros de arquivo Jami (*.gz); Todos os ficheiros (*) + + + + Your account needs to be migrated. Enter your password. + A sua conta tem de ser migrada. Introduza a sua palavra-chave. + + + + Migrating your Jami account... + A migrar a sua conta Jami... + + + + Importing account archive... + A importar ficheiro da conta... + + + + Generating your Jami account... + A gerar a sua conta Jami... + + + + Generating your SIP account... + A gerar a sua conta SIP... + + + + Error creating account + Erro ao criar a conta + + + + PasswordDialog + + + Change Account Password + Alterar a palavra-chave da conta + + + + Enter Current Password + Introduzir a palavra-chave atual + + + + Enter New Password + Introduzir a palavra-chave nova + + + + Confirm New Password + Confirmar a palavra-chave nova + + + + Confirm + Confirmar + + + + Cancel + Cancelar + + + + Current Password Incorrect + A palavra-chave atual está incorreta + + + + PhotoBoothDialog + + + Photobooth + Foto instantânea + + + + PhotoboothWidget + + + Form + Formulário + + + + Photobooth display + Mostrar foto instantânea + + + + Choose File + Escolher Ficheiro + + + + Image Files (*.jpg *.jpeg *.png) + Ficheiros de imagem (*.jpg *.jpeg *.png) + + + + PrivateBridging + + + Choose File + Escolher Ficheiro + + + + Files (*) + Ficheiros (*) + + + + QObject + + + No default mail client found + Cliente de e-mail padrão não encontrado + + + + + Edit Device Name + Editar Nome do Dispositivo + + + + Unlink Device From Account + Desassociar Dispositivo da Conta + + + + Save new device name + Guardar o novo nome do dispositivo + + + + Add as contact + Adicionar como contacto + + + + RingButton + + + Select folder + Select folder + + + + SettingsWidget + + + Form + Formulário + + + + Settings + Configurações + + + + Account + Conta + + + + + General + Geral + + + + + Audio / Video + Áudio / vídeo + + + + System + Sistema + + + + Enable desktop notifications + Ativar notificações no ambiente de trabalho + + + + Keep minimized on close + Manter minimizado ao fechar + + + + Download folder + Pasta de descarregamentos + + + + Save in + Gravar em + + + + Always Recording + Gravar sempre + + + + Updates + Atualizações + + + + Check for updates automatically every + Verificar se existem atualizações a cada + + + + Interval between update checks in days selector + Seletor do intervalo em dias entre verificação de atualizações + + + + days + dias + + + + Check for updates now button + Botão para verificar atualizações agora + + + + Check for updates now + Verificar se existem atualizações + + + + Password + Palavra-chave + + + + + Enable + Ativar + + + + toggle enable notifications + alternar ativar notificações + + + + Toggle keep minimized on close + Alternar manter minimizado ao fechar + + + + Call Recordings + Gravações de chamadas + + + + Toggle automatic updates + Alternar atualizações automáticas + + + + Jami Account + Conta Jami + + + + + Profile + Perfil + + + + + Identity + Identificação + + + + Id + ID + + + + Registered name + Utilizador registado + + + + Type here to register a username + Escreva aqui para registar um nome + + + + Register + Registar + + + + Change Password + Alterar palavra-chave + + + + Export Account + Exportar conta + + + + + Delete Account + Eliminar conta + + + + Linked Devices + Dispositivos associados + + + + Link Another Device + Associar outro dispositivo + + + + Banned Contacts + Contactos Banidos + + + + Format + Formato + + + + Video device framerate selector + Seletor de taxa de fotogramas do vídeo do dispositivo + + + + Preview unavailable + Pré-visualização não disponível + + + + + Advanced Account Settings + Configurações avançadas de conta + + + + SIP Account + Conta SIP + + + + Username + Nome de utilizador + + + + Hostname + Servidor + + + + Proxy + Proxy + + + + Audio + Áudio + + + + Microphone + Microfone + + + + Audio input device selector + Seletor de dispositivo de entrada de áudio + + + + Output Device + Dispositivo de Saída + + + + Choose the output device + Escolha o dispositivo de saída + + + + Video + Vídeo + + + + Device + Dispositivo + + + + Video device selector + Seletor de dispositivo de vídeo + + + + A registered name should not have any spaces and must be at least three letters long + Um nome registado não deve ter espaços e deve ter no mínimo 3 caracteres + + + + This name is already taken + Este nome já foi escolhido por outra pessoa + + + + + Enter an alias + Introduza um apelido + + + + Register this name + Registar este nome + + + + Remove Device + Remover dispositivo + + + + Enter this account's password to confirm the removal of this device + Introduza a palavra-chave desta conta para confirmar a remoção deste dispositivo + + + + Are you sure you wish to remove this device? + Tem a certeza que quer remover este dispositivo? + + + + Export Account Here + Exportar conta aqui + + + + Select A Folder For Your Downloads + Selecionar uma pasta para os seus descarregamentos + + + + Select A Folder For Your Recordings + Selecionar uma pasta para as suas gravações + + + + VideoOverlay + + + Call on Hold + Chamada em Espera + + + + Hold / Unhold + Esperar / Retomar + + + + Chat + Conversa + + + + Mute Mic + Desativar Microfone + + + + Record call + Gravar chamada + + + + Name label + Rótulo do nome + + + + Time elapsed + Tempo decorrido + + + + 00:00 + 00:00 + + + + Hangup + Desligar + + + + Mute Video + Tirar Som ao Vídeo + + + + VideoView + + + Share entire screen + Partilhar ecrã inteiro + + + + Share screen area + Partilhar área do ecrã + + + + Share file + Partilhar ficheiro + + + \ No newline at end of file diff --git a/translations/ring_client_windows_pt_BR.ts b/translations/ring_client_windows_pt_BR.ts new file mode 100644 index 00000000..4020c5b8 --- /dev/null +++ b/translations/ring_client_windows_pt_BR.ts @@ -0,0 +1,1592 @@ + + + AboutDialog + + + + About + Sobre + + + + about button + botão sobre + + + + credits button + botão créditos + + + + Credits + Créditos + + + + Free as in Freedom + + + + + The Microsoft Windows client for Jami. +Jami is a secured and distributed communication software. + O cliente para Microsoft Windows do Jami. +Jami é um programa de comunicação seguro e distribuído. + + + + version + versão + + + + Created by: + Criado por: + + + + Artwork by: + Artwork por: + + + + Based on the SFLPhone project + Baseado no projeto SFLPhone + + + + AccountItemDelegate + + + Add Account + Adicionar Conta + + + + AdvancedSIPSettingsWidget + + + Form + Formulário + + + + Call Settings + Configurações de Chamada + + + + Auto Answer Calls + Atender Chamadas Automaticamente + + + + Enable Custom Ringtone + Ativar Toque Personalizado + + + + Connectivity + Conectividade + + + + STUN Address + Endereço STUN + + + + Use STUN + Usar STUN + + + + Use UPnP + Usar UPnP + + + + Use TURN + Usar TURN + + + + TURN Password + Senha TURN + + + + TURN Username + Usuário TURN + + + + TURN Address + Endereço TURN + + + + Media + Mídia + + + + Enable Video + Habilitar Vídeo + + + + Video Codecs + Codecs de Vídeo + + + + Audio Codecs + Codecs de Áudio + + + + Audio Files (*.wav *.ogg *.opus *.mp3 *aiff *wma) + Arquivos de áudio (*.wav *.ogg *.opus *.mp3 *aiff *wma) + + + + Add a custom ringtone + Adicionar um toque personalizado + + + + AdvancedSettingsWidget + + + Form + Formulário + + + + Call Settings + Configurações de Chamada + + + + Allow Calls From Untrusted Peers + Permitir Chamadas de Usuários Desconhecidos + + + + Auto Answer Calls + Atender Chamadas Automaticamente + + + + Enable Custom Ringtone + Ativar Toque Personalizado + + + + Add a custom ringtone + Adicionar um toque personalizado + + + + Name Server + Servidor de Nome + + + + Address + Endereço + + + + OpenDHT Configuration + Configuração OpenDHT + + + + Enable Proxy + Habilitar Proxy + + + + Bootstrap + Inicialização + + + + Security + Segurança + + + + Private Key Password + Senha chave privada + + + + User Certificate + Certificado do Usuário + + + + Private Key + Chave Privada + + + + CA Certificate + Certificado de CA + + + + Connectivity + Conectividade + + + + Use STUN + Usar STUN + + + + STUN Address + Endereço STUN + + + + Use UPnP + Usar UPnP + + + + Use TURN + Usar TURN + + + + TURN Password + Senha TURN + + + + TURN Username + Usuário TURN + + + + TURN Address + Endereço TURN + + + + Media + Mídia + + + + Enable Video + Habilitar Vídeo + + + + Audio Codecs + Codecs de Áudio + + + + Video Codecs + Codecs de Vídeo + + + + Audio Files (*.wav *.ogg *.opus *.mp3 *aiff *wma) + Arquivos de áudio (*.wav *.ogg *.opus *.mp3 *aiff *wma) + + + + AnimatedOverlay + + + Form + Formulário + + + + BannedItemWidget + + + Form + Formulário + + + + name + nome + + + + id + id + + + + CallWidget + + + Show conversations + Mostrar conversas + + + + Conversations + Conversas + + + + Search contact text input + Entrada de texto para busca de contato + + + + Jami is free software for universal communication which respects the freedoms and privacy of its users. + Jami é um software livre para comunicação universal que respeita as liberdades e privacidade de seus usuários. + + + + + This is your ID. +Copy and share it with your friends! + + + Esse é seu ID +Copiei e compartilhe com seus amigos! + + + + Show ring ID QR code + Mostrar código QR do seu ID do Ring + + + + Share ring ID button + Botão para compartilhar o seu Id do Ring + + + + Double-click to copy + Duplo-clique para copiar + + + + Error while generating QR Code + Erro ao gerar o Código QR + + + + + best name + melhor nome + + + + best Id + melhor Id + + + + Back to homepage button + Botão para voltar à página inicial + + + + Add to contacts + Adicionar aos contatos + + + + Show invites + Mostrar convites + + + + Invites + Convida + + + + + Find a new or existing contact + Encontrar um contato novo ou preexistente + + + + Wants to talk to you! + Quer conversar com você! + + + + Answer incoming call button + Botão para atender chamada + + + + Ignore incoming call button + Botão para ignorar chamada + + + + Answer + Resposta + + + + Ignore + Ignorar + + + + Cancel outgoing call + Cancelar chamada efetuada + + + + Cancel + Cancelar + + + + Start video call + Iniciar videochamada + + + + Start audio call + Iniciar chamada de áudio + + + + Clear conversation + Eliminar a conversa + + + + Remove contact + Remover contato + + + + Block contact + Bloquear contato + + + + Copy number + Copiar número + + + + Search your received invitations + Pesquisar seus convites recebidos + + + + Contact me on Jami + Encontre-me no Jami ! + + + + My Id is : + Meu Id é : + + + + %1 + %1 is the contact username + %1 + + + + %1 + %1 is the contact unique identifier + %1 + + + + Call incoming from %1 + Recebendo chamada de %1 + + + + DeleteAccountDialog + + + Account deletion + Remoção de conta + + + + Do you really want to delete the following account? + Tem certeza que deseja deletar a seguinte conta? + + + + If this account hasn't been exported, or added to another device, it will be irrevocably lost. + Se esta conta não foi exportada, ou adicionada a outro dispositivo, ela será completamente perdida. + + + + Permanently delete account + Deletar conta permanentemente + + + + Delete + Deletar + + + + Cancel account deletion + Cancelar deleção da conta + + + + Cancel + Cancelar + + + + DeviceItemWidget + + + Form + Formulário + + + + Device Id + Id do Dispositivo + + + + this device + este dispositivo + + + + InviteButtonsWidget + + + Accept + Aceitar + + + + Refuse + Recusar + + + + Block + Bloquear + + + + LinkDeviceDialog + + + Dialog + Diálogo + + + + Enter your account password + Entre com a senha de sua conta + + + + Password + Senha + + + + Ok + Ok + + + + Cancel + Cancelar + + + + Exporting account + Exportando conta + + + + Your PIN is + Seu PIN é + + + + PIN + PIN + + + + This pin and the account password should be entered in your device within 10 minutes. + + + + + Close + Fechar + + + + Link Another Device + + + + + Incorrect password + Senha incorreta + + + + Something went wrong. +Please try again later. + + + + + MainWindow + + + Settings + Configurações + + + + Exit + Sair + + + + About + Sobre + + + + Jami + Jami + + + + NameRegistrationDialog + + + Set Registered Name + + + + + Enter your account password + Entre com a senha de sua conta + + + + Password text input + Entrada de texto de senha + + + + Password text entry + Campo de texto da Senha + + + + Password + Senha + + + + Register + Registrar + + + + Cancel + Cancelar + + + + Registering Name + + + + + Something went wrong + + + + + Close + Fechar + + + + Incorrect password + Senha incorreta + + + + Network error + Erro de rede + + + + NewWizardWidget + + + Form + Formulário + + + + Welcome Label + Legenda de boas-vindas + + + + Welcome to + Bem-vindo ao + + + + Welcome Logo + Logotipo de boas-vindas + + + + Create Jami account button + Botão para criar conta do Jami + + + + Push button for Jami account creation start trigger + Botão para acionar a criação da conta do Jami + + + + Create a Jami account + Criar uma conta no Jami + + + + Link device button + Botão para associar dispositivo + + + + Push button for device linkage start trigger + Botão para acionar a associação de dispositivo + + + + Link this device to an account + Associar este dispositivo a uma conta + + + + Create Jami SIP account button + + + + + Push button for Jami SIP account creation start trigger + + + + + Create a SIP account + + + + + Link this device to an existing account + Associar este dispositivo à uma conta existente + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Ubuntu'; font-size:14px; color:#555555;">To link this device to another account, you first </span><span style=" font-family:'Ubuntu'; font-size:14px; font-weight:600; color:#555555;">need to obtain a PIN</span><span style=" font-family:'Ubuntu'; font-size:14px; color:#555555;"> code. To generate the PIN code:</span></p> +<ol style="margin-top: 0px; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; -qt-list-indent: 1;"><li style=" font-family:'Ubuntu'; font-size:14px; color:#555555;" style=" margin-top:12px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:14px;">Go to the </span><span style=" font-size:14px; font-weight:600;">Account management setting</span><span style=" font-size:14px;"> of a previous device</span></li> +<li style=" font-family:'Ubuntu'; font-size:14px; color:#555555;" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:14px;">Choose the </span><span style=" font-size:14px; font-weight:600;">Jami account</span><span style=" font-size:14px;"> you want to use</span></li> +<li style=" font-family:'Ubuntu'; font-size:14px; color:#555555;" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:14px;">Go to the </span><span style=" font-size:14px; font-weight:600;">Devices</span><span style=" font-size:14px;"> tab</span></li> +<li style=" font-family:'Ubuntu'; font-size:14px; color:#555555;" style=" margin-top:0px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:14px;">Select </span><span style=" font-size:14px; font-weight:600;">Add a device</span></li></ol> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Ubuntu'; font-size:14px; color:#555555;">You will get the necessary PIN to complete this form. The PIN is only valid for </span><span style=" font-family:'Ubuntu'; font-size:14px; font-weight:600; color:#555555;">10 minutes</span><span style=" font-family:'Ubuntu'; font-size:10px; color:#555555;">.</span></p></body></html> + + + + + Enter your pin: + Entre o seu PIN: + + + + Or import a file: + Ou importe de arquivo: + + + + Link from exported account archive file + Link do arquivo da conta exportada + + + + + + (None) + + + + + Password: + Senha: + + + + + Profile + Perfil + + + + + Profile name + Nome do perfil + + + + Account + Conta + + + + Register your username. +This will reserve the username so that only you can use it. +Your friends will be able to call you with your usename +instead of using your ID. + + + + + Public username checkbox + Caixa de seleção para nome de usuário público + + + + Checkbox selecting if the user wants a public username + Caixa de seleção para indicar se o usuário deseja um nome de usuário público + + + + Register public username + Registrar nome de usuário público + + + + Public username edit + Editar nome de usuário público + + + + Choose your username + Escolha seu nome de usuário + + + + Password text input + Entrada de texto de senha + + + + Password text entry + Campo de texto da Senha + + + + + Password + Senha + + + + + Password confirmation text input + Campo de texto para confirmação da Senha + + + + Confirm password + Confirmar senha + + + + SIP Account + Conta SIP + + + + SIP Server edit + + + + + Server + + + + + SIP proxy input + + + + + SIP proxy text entry + + + + + Proxy + Proxy + + + + SIP username input + Entrada de usuário SIP + + + + SIP Password text entry + + + + + Username + Nome de usuário + + + + + SIP Password text input + + + + + Generating your Jami account… + Gerando sua conta do Jami... + + + + Previous page button + Botão da página anterior + + + + push button to access previous page of wizard + Pressione botão para acessar a página anterior do assistente + + + + Previous + Anterior + + + + Cancel account create/link + + + + + push button to cancel account creation or linking + + + + + Back + Voltar + + + + Next page Button + Botão da próxima página + + + + Push button to access next page of wizard + Pressione botão para acessar próxima página do assistente + + + + Next + Próximo + + + + Open File + Abrir arquivo + + + + Jami archive files (*.gz); All files (*) + + + + + Your account needs to be migrated. Enter your password. + Sua conta precisa ser migrada. Entre com sua senha. + + + + Migrating your Jami account... + Migrando sua conta do Jami... + + + + Importing account archive... + Importando arquivo da conta... + + + + Generating your Jami account... + Gerando sua conta do Jami... + + + + Generating your SIP account... + + + + + Error creating account + Erro ao criar conta + + + + PasswordDialog + + + Change Account Password + + + + + Enter Current Password + + + + + Enter New Password + + + + + Confirm New Password + + + + + Confirm + + + + + Cancel + Cancelar + + + + Current Password Incorrect + + + + + PhotoBoothDialog + + + Photobooth + Foto instantânea + + + + PhotoboothWidget + + + Form + Formulário + + + + Photobooth display + Exibir foto instantânea + + + + Choose File + Escolher Arquivo + + + + Image Files (*.jpg *.jpeg *.png) + + + + + PrivateBridging + + + Choose File + Escolher Arquivo + + + + Files (*) + Arquivos (*) + + + + QObject + + + No default mail client found + Cliente de e-mail não encontrado + + + + + Edit Device Name + Editar Nome do Dispositivo + + + + Unlink Device From Account + Desassociar Este Dispositivo Da Conta + + + + Save new device name + + + + + Add as contact + + + + + RingButton + + + Select folder + Selecionar pasta + + + + SettingsWidget + + + Form + Formulário + + + + Settings + Configurações + + + + Account + Conta + + + + + General + Geral + + + + + Audio / Video + Áudio / vídeo + + + + System + Sistema + + + + Enable desktop notifications + + + + + Keep minimized on close + Manter minimizado ao fechar + + + + Download folder + Pasta de downloads + + + + Save in + Salvar em + + + + Always Recording + + + + + Updates + Atualizações + + + + Check for updates automatically every + + + + + Interval between update checks in days selector + Seletor do intervalo da verificação de atualizaçôes em dias + + + + days + dias + + + + Check for updates now button + Botão para verificar atualizações agora + + + + Check for updates now + Checar por atualizações agora + + + + Password + Senha + + + + + Enable + Habilitar + + + + toggle enable notifications + + + + + Toggle keep minimized on close + + + + + Call Recordings + + + + + Toggle automatic updates + + + + + Jami Account + + + + + + Profile + Perfil + + + + + Identity + Identificação + + + + Id + ID + + + + Registered name + Usuário registrado + + + + Type here to register a username + + + + + Register + Registrar + + + + Change Password + Alterar senha + + + + Export Account + Exportar Conta + + + + + Delete Account + + + + + Linked Devices + + + + + Link Another Device + + + + + Banned Contacts + Contatos Banidos + + + + Format + + + + + Video device framerate selector + + + + + Preview unavailable + + + + + + Advanced Account Settings + + + + + SIP Account + Conta SIP + + + + Username + Nome de usuário + + + + Hostname + Servidor + + + + Proxy + Proxy + + + + Audio + Áudio + + + + Microphone + Microfone + + + + Audio input device selector + Seletor de dispositivo de entrada de áudio + + + + Output Device + Dispositivo de saída + + + + Choose the output device + + + + + Video + Vídeo + + + + Device + Dispositivo + + + + Video device selector + Seletor de dispositivo de vídeo + + + + A registered name should not have any spaces and must be at least three letters long + + + + + This name is already taken + + + + + + Enter an alias + + + + + Register this name + + + + + Remove Device + + + + + Enter this account's password to confirm the removal of this device + + + + + Are you sure you wish to remove this device? + + + + + Export Account Here + + + + + Select A Folder For Your Downloads + + + + + Select A Folder For Your Recordings + + + + + VideoOverlay + + + Call on Hold + Chamada em espera + + + + Hold / Unhold + Esperar / Retomar + + + + Chat + Conversa + + + + Mute Mic + Desativar microfone + + + + Record call + Gravar chamada + + + + Name label + Nome do rótulo + + + + Time elapsed + Tempo decorrido + + + + 00:00 + 00:00 + + + + Hangup + Desligar + + + + Mute Video + Desativar vídeo + + + + VideoView + + + Share entire screen + Compartilhar tela inteira + + + + Share screen area + Compartilhar área da tela + + + + Share file + Compartilhar arquivo + + + \ No newline at end of file diff --git a/translations/ring_client_windows_pt_PT.ts b/translations/ring_client_windows_pt_PT.ts new file mode 100644 index 00000000..dd4f0f57 --- /dev/null +++ b/translations/ring_client_windows_pt_PT.ts @@ -0,0 +1,1606 @@ + + + AboutDialog + + + + About + Sobre + + + + about button + botão sobre + + + + credits button + botão créditos + + + + Credits + Créditos + + + + Free as in Freedom + Livre como em Liberdade + + + + The Microsoft Windows client for Jami. +Jami is a secured and distributed communication software. + O cliente Microsoft Windows para o Jami +O Jami é um programa de comunicação distribuído e seguro. + + + + version + versão + + + + Created by: + Criado por: + + + + Artwork by: + Arte por: + + + + Based on the SFLPhone project + Baseado no projeto SFLPhone + + + + AccountItemDelegate + + + Add Account + Adicionar Conta + + + + AdvancedSIPSettingsWidget + + + Form + Formulário + + + + Call Settings + Configurações de chamadas + + + + Auto Answer Calls + Atender chamadas automaticamente + + + + Enable Custom Ringtone + Ativar toque de chamada personalizado + + + + Connectivity + Conectividade + + + + STUN Address + Endereço STUN + + + + Use STUN + Usar STUN + + + + Use UPnP + Usar UPnP + + + + Use TURN + Usar TURN + + + + TURN Password + Palavra-chave TURN + + + + TURN Username + Nome de utilizador TURN + + + + TURN Address + Endereço TURN + + + + Media + Média + + + + Enable Video + Ativar Vídeo + + + + Video Codecs + Codecs de vídeo + + + + Audio Codecs + Codecs de áudio + + + + Audio Files (*.wav *.ogg *.opus *.mp3 *aiff *wma) + Ficheiros de áudio (*.wav *.ogg *.opus *.mp3 *aiff *wma) + + + + Add a custom ringtone + Adicionar um toque de chamada personalizado + + + + AdvancedSettingsWidget + + + Form + Formulário + + + + Call Settings + Configurações de chamadas + + + + Allow Calls From Untrusted Peers + Permitir chamadas de utilizadores desconhecidos + + + + Auto Answer Calls + Atender chamadas automaticamente + + + + Enable Custom Ringtone + Ativar toque de chamada personalizado + + + + Add a custom ringtone + Adicionar um toque de chamada personalizado + + + + Name Server + Nome do servidor + + + + Address + Endereço + + + + OpenDHT Configuration + Configuração OpenDHT + + + + Enable Proxy + Ativar Proxy + + + + Bootstrap + Inicialização + + + + Security + Segurança + + + + Private Key Password + Palavra-chave da Chave Privada + + + + User Certificate + Certificado do Utilizador + + + + Private Key + Chave privada + + + + CA Certificate + Certificado CA + + + + Connectivity + Conectividade + + + + Use STUN + Usar STUN + + + + STUN Address + Endereço STUN + + + + Use UPnP + Usar UPnP + + + + Use TURN + Usar TURN + + + + TURN Password + Palavra-chave TURN + + + + TURN Username + Nome de utilizador TURN + + + + TURN Address + Endereço TURN + + + + Media + Média + + + + Enable Video + Ativar Vídeo + + + + Audio Codecs + Codecs de áudio + + + + Video Codecs + Codecs de vídeo + + + + Audio Files (*.wav *.ogg *.opus *.mp3 *aiff *wma) + Ficheiros de áudio (*.wav *.ogg *.opus *.mp3 *aiff *wma) + + + + AnimatedOverlay + + + Form + Formulário + + + + BannedItemWidget + + + Form + Formulário + + + + name + nome + + + + id + id + + + + CallWidget + + + Show conversations + Ver conversações + + + + Conversations + Conversas + + + + Search contact text input + Entrada de texto para pesquisa de contacto + + + + Jami is free software for universal communication which respects the freedoms and privacy of its users. + O Jami é um programa livre para comunicação universal que respeita as liberdades e privacidade dos seus utilizadores. + + + + + This is your ID. +Copy and share it with your friends! + + + Este é o seu ID. +Copie-o e partilhe-o com os seus amigos! + + + + + Show ring ID QR code + Mostrar código QR do seu ID do Ring + + + + Share ring ID button + Botão para partilhar o seu ID do Ring + + + + Double-click to copy + Duplo-clique para copiar + + + + Error while generating QR Code + Erro ao gerar o Código QR + + + + + best name + melhor nome + + + + best Id + melhor Id + + + + Back to homepage button + Botão para voltar à página inicial + + + + Add to contacts + Adicionar aos contactos + + + + Show invites + Mostrar convites + + + + Invites + Convites + + + + + Find a new or existing contact + Procurar um contacto novo ou existente + + + + Wants to talk to you! + Quer conversar consigo! + + + + Answer incoming call button + Botão para atender chamada + + + + Ignore incoming call button + Botão para ignorar chamada + + + + Answer + Resposta + + + + Ignore + Ignorar + + + + Cancel outgoing call + Cancelar chamada efetuada + + + + Cancel + Cancelar + + + + Start video call + Começar chamada de vídeo + + + + Start audio call + Começar chamada de áudio + + + + Clear conversation + Limpar conversação + + + + Remove contact + Remover contacto + + + + Block contact + Bloquear contacto + + + + Copy number + Copiar número + + + + Search your received invitations + Pesquisar os seus convites recebidos + + + + Contact me on Jami + Contacte-me no Jami + + + + My Id is : + O meu ID é: + + + + %1 + %1 is the contact username + %1 + + + + %1 + %1 is the contact unique identifier + %1 + + + + Call incoming from %1 + A receber chamada de %1 + + + + DeleteAccountDialog + + + Account deletion + Eliminação de conta + + + + Do you really want to delete the following account? + Tem certeza que quer eliminar a seguinte conta? + + + + If this account hasn't been exported, or added to another device, it will be irrevocably lost. + Se esta conta não foi exportada ou adicionada a outro dispositivo, ela será perdida. + + + + Permanently delete account + Eliminar conta permanentemente + + + + Delete + Eliminar + + + + Cancel account deletion + Cancelar eliminação da conta + + + + Cancel + Cancelar + + + + DeviceItemWidget + + + Form + Formulário + + + + Device Id + ID do dispositivo + + + + this device + este dispositivo + + + + InviteButtonsWidget + + + Accept + Aceitar + + + + Refuse + Recusar + + + + Block + Bloquear + + + + LinkDeviceDialog + + + Dialog + Diálogo + + + + Enter your account password + Introduza a palavra-chave da sua conta + + + + Password + Palavra-chave + + + + Ok + OK + + + + Cancel + Cancelar + + + + Exporting account + Exportar a conta + + + + Your PIN is + O seu PIN é + + + + PIN + PIN + + + + This pin and the account password should be entered in your device within 10 minutes. + Este PIN e a palavra-chave devem ser inseridos no seu novo dispositivo nos próximos 10 minutos. + + + + Close + Fechar + + + + Link Another Device + Associar outro dispositivo + + + + Incorrect password + Palavra-chave incorreta + + + + Something went wrong. +Please try again later. + Algo correu mal. +Por favor tente de novo mais tarde. + + + + MainWindow + + + Settings + Configurações + + + + Exit + Sair + + + + About + Sobre + + + + Jami + Jami + + + + NameRegistrationDialog + + + Set Registered Name + Definir o nome registado + + + + Enter your account password + Introduza a palavra-chave da sua conta + + + + Password text input + Entrada de texto da palavra-chave + + + + Password text entry + Campo de texto da palavra-chave + + + + Password + Palavra-chave + + + + Register + Registar + + + + Cancel + Cancelar + + + + Registering Name + Registar o nome + + + + Something went wrong + Algo correu mal + + + + Close + Fechar + + + + Incorrect password + Palavra-chave incorreta + + + + Network error + Erro de rede + + + + NewWizardWidget + + + Form + Formulário + + + + Welcome Label + Rótulo de Boas-Vindas + + + + Welcome to + Bem-vindo(a) ao + + + + Welcome Logo + Logótipo de Boas-Vindas + + + + Create Jami account button + Botão para criar conta Jami + + + + Push button for Jami account creation start trigger + Botão para acionar a criação da conta do Jami + + + + Create a Jami account + Criar uma conta Jami + + + + Link device button + Botão para associar dispositivo + + + + Push button for device linkage start trigger + Botão para acionar a associação de dispositivo + + + + Link this device to an account + Associar este dispositivo a uma conta + + + + Create Jami SIP account button + Botão para criar a conta SIP Jami + + + + Push button for Jami SIP account creation start trigger + Botão para acionar a criação da conta SIP Jami + + + + Create a SIP account + Criar uma conta SIP + + + + Link this device to an existing account + Associar este dispositivo a uma conta existente + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Ubuntu'; font-size:14px; color:#555555;">To link this device to another account, you first </span><span style=" font-family:'Ubuntu'; font-size:14px; font-weight:600; color:#555555;">need to obtain a PIN</span><span style=" font-family:'Ubuntu'; font-size:14px; color:#555555;"> code. To generate the PIN code:</span></p> +<ol style="margin-top: 0px; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; -qt-list-indent: 1;"><li style=" font-family:'Ubuntu'; font-size:14px; color:#555555;" style=" margin-top:12px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:14px;">Go to the </span><span style=" font-size:14px; font-weight:600;">Account management setting</span><span style=" font-size:14px;"> of a previous device</span></li> +<li style=" font-family:'Ubuntu'; font-size:14px; color:#555555;" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:14px;">Choose the </span><span style=" font-size:14px; font-weight:600;">Jami account</span><span style=" font-size:14px;"> you want to use</span></li> +<li style=" font-family:'Ubuntu'; font-size:14px; color:#555555;" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:14px;">Go to the </span><span style=" font-size:14px; font-weight:600;">Devices</span><span style=" font-size:14px;"> tab</span></li> +<li style=" font-family:'Ubuntu'; font-size:14px; color:#555555;" style=" margin-top:0px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:14px;">Select </span><span style=" font-size:14px; font-weight:600;">Add a device</span></li></ol> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Ubuntu'; font-size:14px; color:#555555;">You will get the necessary PIN to complete this form. The PIN is only valid for </span><span style=" font-family:'Ubuntu'; font-size:14px; font-weight:600; color:#555555;">10 minutes</span><span style=" font-family:'Ubuntu'; font-size:10px; color:#555555;">.</span></p></body></html> + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Ubuntu'; font-size:14px; color:#555555;">Para associar este dispositivo a outra conta, primeiro </span><span style=" font-family:'Ubuntu'; font-size:14px; font-weight:600; color:#555555;">tem de obter um código PIN.</span><span style=" font-family:'Ubuntu'; font-size:14px; color:#555555;">Para gerar o código PIN:</span></p> +<ol style="margin-top: 0px; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; -qt-list-indent: 1;"><li style=" font-family:'Ubuntu'; font-size:14px; color:#555555;" style=" margin-top:12px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:14px;">Aceda à </span><span style=" font-size:14px; font-weight:600;">configuração de gestão de conta</span><span style=" font-size:14px;"> de um dispositivo anterior</span></li> +<li style=" font-family:'Ubuntu'; font-size:14px; color:#555555;" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:14px;">Escolha a </span><span style=" font-size:14px; font-weight:600;">conta Jami</span><span style=" font-size:14px;"> quer quer usar</span></li> +<li style=" font-family:'Ubuntu'; font-size:14px; color:#555555;" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:14px;">Aceda à aba </span><span style=" font-size:14px; font-weight:600;">Dispositivos</span><span style=" font-size:14px;"> </span></li> +<li style=" font-family:'Ubuntu'; font-size:14px; color:#555555;" style=" margin-top:0px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:14px;">Selecione </span><span style=" font-size:14px; font-weight:600;">Adicionar dispositivo</span></li></ol> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Ubuntu'; font-size:14px; color:#555555;">Irá obter o PIN necessário para completar este formulário. O código PIN é válido apenas durante </span><span style=" font-family:'Ubuntu'; font-size:14px; font-weight:600; color:#555555;">10 minutos</span><span style=" font-family:'Ubuntu'; font-size:10px; color:#555555;">.</span></p></body></html> + + + + Enter your pin: + Introduza o seu PIN: + + + + Or import a file: + Ou importe de um ficheiro: + + + + Link from exported account archive file + Link do ficheiro da conta exportada + + + + + + (None) + (nenhum) + + + + Password: + Palavra-chave: + + + + + Profile + Perfil + + + + + Profile name + Nome do perfil + + + + Account + Conta + + + + Register your username. +This will reserve the username so that only you can use it. +Your friends will be able to call you with your usename +instead of using your ID. + Registe o seu nome de utilizador. +Isto irá reservar o nome de utilizador para que apenas você o possa utilizar. +Os seus amigos serão capazes de contactá-lo com seu nome de +utilizador em vez do seu ID. + + + + Public username checkbox + Caixa de visto para o nome público de utilizador + + + + Checkbox selecting if the user wants a public username + Caixa de visto para indicar se o utilizador quer um nome público de utilizador + + + + Register public username + Registar nome de utilizador público + + + + Public username edit + Editar nome público de utilizador + + + + Choose your username + Escolha o seu nome de utilizador + + + + Password text input + Entrada de texto da palavra-chave + + + + Password text entry + Campo de texto da palavra-chave + + + + + Password + Palavra-chave + + + + + Password confirmation text input + Campo de texto para confirmação da palavra-chave + + + + Confirm password + Confirmar palavra-chave + + + + SIP Account + Conta SIP + + + + SIP Server edit + Editar servidor SIP + + + + Server + Servidor + + + + SIP proxy input + Entrada do proxy SIP + + + + SIP proxy text entry + Campo de texto do proxy SIP + + + + Proxy + Proxy + + + + SIP username input + Entrada de nome de utilizador SIP + + + + SIP Password text entry + Campo de texto da palavra-chave SIP + + + + Username + Nome de utilizador + + + + + SIP Password text input + Entrada de texto da palavra-chave SIP + + + + Generating your Jami account… + A gerar a sua conta Jami... + + + + Previous page button + Botão de página anterior + + + + push button to access previous page of wizard + Botão de pressionar para aceder à página anterior do assistente + + + + Previous + Anterior + + + + Cancel account create/link + Cancelar a criação de conta / associação + + + + push button to cancel account creation or linking + botão para cancelar criação de conta ou associação + + + + Back + Voltar + + + + Next page Button + Botão de página seguinte + + + + Push button to access next page of wizard + Botão de pressionar para aceder à página seguinte do assistente + + + + Next + Próximo + + + + Open File + Abrir Ficheiro + + + + Jami archive files (*.gz); All files (*) + Ficheiros de arquivo Jami (*.gz); Todos os ficheiros (*) + + + + Your account needs to be migrated. Enter your password. + A sua conta tem de ser migrada. Introduza a sua palavra-chave. + + + + Migrating your Jami account... + A migrar a sua conta Jami... + + + + Importing account archive... + A importar ficheiro da conta... + + + + Generating your Jami account... + A gerar a sua conta Jami... + + + + Generating your SIP account... + A gerar a sua conta SIP... + + + + Error creating account + Erro ao criar a conta + + + + PasswordDialog + + + Change Account Password + Alterar a palavra-chave da conta + + + + Enter Current Password + Introduzir a palavra-chave atual + + + + Enter New Password + Introduzir a palavra-chave nova + + + + Confirm New Password + Confirmar a palavra-chave nova + + + + Confirm + Confirmar + + + + Cancel + Cancelar + + + + Current Password Incorrect + A palavra-chave atual está incorreta + + + + PhotoBoothDialog + + + Photobooth + Foto instantânea + + + + PhotoboothWidget + + + Form + Formulário + + + + Photobooth display + Mostrar foto instantânea + + + + Choose File + Escolher Ficheiro + + + + Image Files (*.jpg *.jpeg *.png) + Ficheiros de imagem (*.jpg *.jpeg *.png) + + + + PrivateBridging + + + Choose File + Escolher Ficheiro + + + + Files (*) + Ficheiros (*) + + + + QObject + + + No default mail client found + Cliente de e-mail padrão não encontrado + + + + + Edit Device Name + Editar Nome do Dispositivo + + + + Unlink Device From Account + Desassociar Dispositivo da Conta + + + + Save new device name + Guardar o novo nome do dispositivo + + + + Add as contact + Adicionar como contacto + + + + RingButton + + + Select folder + Select folder + + + + SettingsWidget + + + Form + Formulário + + + + Settings + Configurações + + + + Account + Conta + + + + + General + Geral + + + + + Audio / Video + Áudio / vídeo + + + + System + Sistema + + + + Enable desktop notifications + Ativar notificações no ambiente de trabalho + + + + Keep minimized on close + Manter minimizado ao fechar + + + + Download folder + Pasta de descarregamentos + + + + Save in + Gravar em + + + + Always Recording + Gravar sempre + + + + Updates + Atualizações + + + + Check for updates automatically every + Verificar se existem atualizações a cada + + + + Interval between update checks in days selector + Seletor do intervalo em dias entre verificação de atualizações + + + + days + dias + + + + Check for updates now button + Botão para verificar atualizações agora + + + + Check for updates now + Verificar se existem atualizações + + + + Password + Palavra-chave + + + + + Enable + Ativar + + + + toggle enable notifications + alternar ativar notificações + + + + Toggle keep minimized on close + Alternar manter minimizado ao fechar + + + + Call Recordings + Gravações de chamadas + + + + Toggle automatic updates + Alternar atualizações automáticas + + + + Jami Account + Conta Jami + + + + + Profile + Perfil + + + + + Identity + Identificação + + + + Id + ID + + + + Registered name + Utilizador registado + + + + Type here to register a username + Escreva aqui para registar um nome + + + + Register + Registar + + + + Change Password + Alterar palavra-chave + + + + Export Account + Exportar conta + + + + + Delete Account + Eliminar conta + + + + Linked Devices + Dispositivos associados + + + + Link Another Device + Associar outro dispositivo + + + + Banned Contacts + Contactos Banidos + + + + Format + Formato + + + + Video device framerate selector + Seletor de taxa de fotogramas do vídeo do dispositivo + + + + Preview unavailable + Pré-visualização não disponível + + + + + Advanced Account Settings + Configurações avançadas de conta + + + + SIP Account + Conta SIP + + + + Username + Nome de utilizador + + + + Hostname + Servidor + + + + Proxy + Proxy + + + + Audio + Áudio + + + + Microphone + Microfone + + + + Audio input device selector + Seletor de dispositivo de entrada de áudio + + + + Output Device + Dispositivo de Saída + + + + Choose the output device + Escolha o dispositivo de saída + + + + Video + Vídeo + + + + Device + Dispositivo + + + + Video device selector + Seletor de dispositivo de vídeo + + + + A registered name should not have any spaces and must be at least three letters long + Um nome registado não deve ter espaços e deve ter no mínimo 3 caracteres + + + + This name is already taken + Este nome já foi escolhido por outra pessoa + + + + + Enter an alias + Introduza um apelido + + + + Register this name + Registar este nome + + + + Remove Device + Remover dispositivo + + + + Enter this account's password to confirm the removal of this device + Introduza a palavra-chave desta conta para confirmar a remoção deste dispositivo + + + + Are you sure you wish to remove this device? + Tem a certeza que quer remover este dispositivo? + + + + Export Account Here + Exportar conta aqui + + + + Select A Folder For Your Downloads + Selecionar uma pasta para os seus descarregamentos + + + + Select A Folder For Your Recordings + Selecionar uma pasta para as suas gravações + + + + VideoOverlay + + + Call on Hold + Chamada em Espera + + + + Hold / Unhold + Esperar / Retomar + + + + Chat + Conversa + + + + Mute Mic + Desativar Microfone + + + + Record call + Gravar chamada + + + + Name label + Rótulo do nome + + + + Time elapsed + Tempo decorrido + + + + 00:00 + 00:00 + + + + Hangup + Desligar + + + + Mute Video + Tirar Som ao Vídeo + + + + VideoView + + + Share entire screen + Partilhar ecrã inteiro + + + + Share screen area + Partilhar área do ecrã + + + + Share file + Partilhar ficheiro + + + \ No newline at end of file diff --git a/translations/ring_client_windows_ro.ts b/translations/ring_client_windows_ro.ts new file mode 100644 index 00000000..5271bdfb --- /dev/null +++ b/translations/ring_client_windows_ro.ts @@ -0,0 +1,1589 @@ + + + AboutDialog + + + + About + + + + + about button + + + + + credits button + + + + + Credits + Credite + + + + Free as in Freedom + + + + + The Microsoft Windows client for Jami. +Jami is a secured and distributed communication software. + + + + + version + + + + + Created by: + + + + + Artwork by: + + + + + Based on the SFLPhone project + + + + + AccountItemDelegate + + + Add Account + + + + + AdvancedSIPSettingsWidget + + + Form + + + + + Call Settings + + + + + Auto Answer Calls + + + + + Enable Custom Ringtone + + + + + Connectivity + + + + + STUN Address + + + + + Use STUN + + + + + Use UPnP + + + + + Use TURN + + + + + TURN Password + + + + + TURN Username + + + + + TURN Address + + + + + Media + Media + + + + Enable Video + Activează video + + + + Video Codecs + + + + + Audio Codecs + + + + + Audio Files (*.wav *.ogg *.opus *.mp3 *aiff *wma) + + + + + Add a custom ringtone + + + + + AdvancedSettingsWidget + + + Form + + + + + Call Settings + + + + + Allow Calls From Untrusted Peers + + + + + Auto Answer Calls + + + + + Enable Custom Ringtone + + + + + Add a custom ringtone + + + + + Name Server + + + + + Address + + + + + OpenDHT Configuration + + + + + Enable Proxy + + + + + Bootstrap + + + + + Security + Seuritate + + + + Private Key Password + + + + + User Certificate + + + + + Private Key + + + + + CA Certificate + + + + + Connectivity + + + + + Use STUN + + + + + STUN Address + + + + + Use UPnP + + + + + Use TURN + + + + + TURN Password + + + + + TURN Username + + + + + TURN Address + + + + + Media + Media + + + + Enable Video + Activează video + + + + Audio Codecs + + + + + Video Codecs + + + + + Audio Files (*.wav *.ogg *.opus *.mp3 *aiff *wma) + + + + + AnimatedOverlay + + + Form + + + + + BannedItemWidget + + + Form + + + + + name + + + + + id + + + + + CallWidget + + + Show conversations + + + + + Conversations + + + + + Search contact text input + + + + + Jami is free software for universal communication which respects the freedoms and privacy of its users. + + + + + + This is your ID. +Copy and share it with your friends! + + + + + + Show ring ID QR code + + + + + Share ring ID button + + + + + Double-click to copy + + + + + Error while generating QR Code + + + + + + best name + + + + + best Id + + + + + Back to homepage button + + + + + Add to contacts + Adaugă la contacte + + + + Show invites + + + + + Invites + + + + + + Find a new or existing contact + + + + + Wants to talk to you! + + + + + Answer incoming call button + + + + + Ignore incoming call button + + + + + Answer + + + + + Ignore + + + + + Cancel outgoing call + + + + + Cancel + + + + + Start video call + + + + + Start audio call + + + + + Clear conversation + + + + + Remove contact + + + + + Block contact + Blocați contactul + + + + Copy number + Copiați numărul + + + + Search your received invitations + + + + + Contact me on Jami + + + + + My Id is : + + + + + %1 + %1 is the contact username + + + + + %1 + %1 is the contact unique identifier + + + + + Call incoming from %1 + + + + + DeleteAccountDialog + + + Account deletion + + + + + Do you really want to delete the following account? + + + + + If this account hasn't been exported, or added to another device, it will be irrevocably lost. + + + + + Permanently delete account + + + + + Delete + Șterge + + + + Cancel account deletion + + + + + Cancel + + + + + DeviceItemWidget + + + Form + + + + + Device Id + + + + + this device + + + + + InviteButtonsWidget + + + Accept + Acceptă + + + + Refuse + Refuzați + + + + Block + Blochează + + + + LinkDeviceDialog + + + Dialog + + + + + Enter your account password + + + + + Password + Parola + + + + Ok + + + + + Cancel + + + + + Exporting account + + + + + Your PIN is + + + + + PIN + + + + + This pin and the account password should be entered in your device within 10 minutes. + + + + + Close + + + + + Link Another Device + + + + + Incorrect password + + + + + Something went wrong. +Please try again later. + + + + + MainWindow + + + Settings + Setari + + + + Exit + + + + + About + + + + + Jami + + + + + NameRegistrationDialog + + + Set Registered Name + + + + + Enter your account password + + + + + Password text input + + + + + Password text entry + + + + + Password + Parola + + + + Register + Registrare + + + + Cancel + + + + + Registering Name + + + + + Something went wrong + + + + + Close + + + + + Incorrect password + + + + + Network error + + + + + NewWizardWidget + + + Form + + + + + Welcome Label + + + + + Welcome to + + + + + Welcome Logo + + + + + Create Jami account button + + + + + Push button for Jami account creation start trigger + + + + + Create a Jami account + Creați un cont Jami + + + + Link device button + + + + + Push button for device linkage start trigger + + + + + Link this device to an account + + + + + Create Jami SIP account button + + + + + Push button for Jami SIP account creation start trigger + + + + + Create a SIP account + + + + + Link this device to an existing account + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Ubuntu'; font-size:14px; color:#555555;">To link this device to another account, you first </span><span style=" font-family:'Ubuntu'; font-size:14px; font-weight:600; color:#555555;">need to obtain a PIN</span><span style=" font-family:'Ubuntu'; font-size:14px; color:#555555;"> code. To generate the PIN code:</span></p> +<ol style="margin-top: 0px; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; -qt-list-indent: 1;"><li style=" font-family:'Ubuntu'; font-size:14px; color:#555555;" style=" margin-top:12px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:14px;">Go to the </span><span style=" font-size:14px; font-weight:600;">Account management setting</span><span style=" font-size:14px;"> of a previous device</span></li> +<li style=" font-family:'Ubuntu'; font-size:14px; color:#555555;" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:14px;">Choose the </span><span style=" font-size:14px; font-weight:600;">Jami account</span><span style=" font-size:14px;"> you want to use</span></li> +<li style=" font-family:'Ubuntu'; font-size:14px; color:#555555;" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:14px;">Go to the </span><span style=" font-size:14px; font-weight:600;">Devices</span><span style=" font-size:14px;"> tab</span></li> +<li style=" font-family:'Ubuntu'; font-size:14px; color:#555555;" style=" margin-top:0px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:14px;">Select </span><span style=" font-size:14px; font-weight:600;">Add a device</span></li></ol> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Ubuntu'; font-size:14px; color:#555555;">You will get the necessary PIN to complete this form. The PIN is only valid for </span><span style=" font-family:'Ubuntu'; font-size:14px; font-weight:600; color:#555555;">10 minutes</span><span style=" font-family:'Ubuntu'; font-size:10px; color:#555555;">.</span></p></body></html> + + + + + Enter your pin: + + + + + Or import a file: + + + + + Link from exported account archive file + + + + + + + (None) + + + + + Password: + + + + + + Profile + + + + + + Profile name + + + + + Account + + + + + Register your username. +This will reserve the username so that only you can use it. +Your friends will be able to call you with your usename +instead of using your ID. + + + + + Public username checkbox + + + + + Checkbox selecting if the user wants a public username + + + + + Register public username + + + + + Public username edit + + + + + Choose your username + + + + + Password text input + + + + + Password text entry + + + + + + Password + Parola + + + + + Password confirmation text input + + + + + Confirm password + Confirmă parola + + + + SIP Account + + + + + SIP Server edit + + + + + Server + + + + + SIP proxy input + + + + + SIP proxy text entry + + + + + Proxy + + + + + SIP username input + + + + + SIP Password text entry + + + + + Username + Nume de utilizator + + + + + SIP Password text input + + + + + Generating your Jami account… + + + + + Previous page button + + + + + push button to access previous page of wizard + + + + + Previous + + + + + Cancel account create/link + + + + + push button to cancel account creation or linking + + + + + Back + Înapoi + + + + Next page Button + + + + + Push button to access next page of wizard + + + + + Next + Înainte + + + + Open File + + + + + Jami archive files (*.gz); All files (*) + + + + + Your account needs to be migrated. Enter your password. + + + + + Migrating your Jami account... + + + + + Importing account archive... + + + + + Generating your Jami account... + + + + + Generating your SIP account... + + + + + Error creating account + + + + + PasswordDialog + + + Change Account Password + + + + + Enter Current Password + + + + + Enter New Password + + + + + Confirm New Password + + + + + Confirm + + + + + Cancel + + + + + Current Password Incorrect + + + + + PhotoBoothDialog + + + Photobooth + + + + + PhotoboothWidget + + + Form + + + + + Photobooth display + + + + + Choose File + + + + + Image Files (*.jpg *.jpeg *.png) + + + + + PrivateBridging + + + Choose File + + + + + Files (*) + + + + + QObject + + + No default mail client found + + + + + + Edit Device Name + + + + + Unlink Device From Account + + + + + Save new device name + + + + + Add as contact + + + + + RingButton + + + Select folder + + + + + SettingsWidget + + + Form + + + + + Settings + Setari + + + + Account + + + + + + General + General + + + + + Audio / Video + + + + + System + Sistem + + + + Enable desktop notifications + + + + + Keep minimized on close + + + + + Download folder + + + + + Save in + + + + + Always Recording + + + + + Updates + + + + + Check for updates automatically every + + + + + Interval between update checks in days selector + + + + + days + + + + + Check for updates now button + + + + + Check for updates now + + + + + Password + Parola + + + + + Enable + + + + + toggle enable notifications + + + + + Toggle keep minimized on close + + + + + Call Recordings + + + + + Toggle automatic updates + + + + + Jami Account + + + + + + Profile + + + + + + Identity + + + + + Id + + + + + Registered name + + + + + Type here to register a username + + + + + Register + Registrare + + + + Change Password + + + + + Export Account + + + + + + Delete Account + + + + + Linked Devices + + + + + Link Another Device + + + + + Banned Contacts + + + + + Format + + + + + Video device framerate selector + + + + + Preview unavailable + + + + + + Advanced Account Settings + + + + + SIP Account + + + + + Username + Nume de utilizator + + + + Hostname + Hostname + + + + Proxy + + + + + Audio + Audio + + + + Microphone + + + + + Audio input device selector + + + + + Output Device + + + + + Choose the output device + + + + + Video + Video + + + + Device + + + + + Video device selector + + + + + A registered name should not have any spaces and must be at least three letters long + + + + + This name is already taken + + + + + + Enter an alias + + + + + Register this name + + + + + Remove Device + + + + + Enter this account's password to confirm the removal of this device + + + + + Are you sure you wish to remove this device? + + + + + Export Account Here + + + + + Select A Folder For Your Downloads + + + + + Select A Folder For Your Recordings + + + + + VideoOverlay + + + Call on Hold + + + + + Hold / Unhold + + + + + Chat + + + + + Mute Mic + + + + + Record call + + + + + Name label + + + + + Time elapsed + + + + + 00:00 + + + + + Hangup + + + + + Mute Video + + + + + VideoView + + + Share entire screen + + + + + Share screen area + + + + + Share file + Distribuie fișierul + + + \ No newline at end of file diff --git a/translations/ring_client_windows_ro_RO.ts b/translations/ring_client_windows_ro_RO.ts new file mode 100644 index 00000000..6a83867a --- /dev/null +++ b/translations/ring_client_windows_ro_RO.ts @@ -0,0 +1,1598 @@ + + + AboutDialog + + + + About + Despre + + + + about button + butonul Informații + + + + credits button + butonul Merite + + + + Credits + Merite + + + + Free as in Freedom + + + + + The Microsoft Windows client for Jami. +Jami is a secured and distributed communication software. + + + + + version + + + + + Created by: + + + + + Artwork by: + + + + + Based on the SFLPhone project + + + + + AccountItemDelegate + + + Add Account + + + + + AdvancedSIPSettingsWidget + + + Form + + + + + Call Settings + + + + + Auto Answer Calls + + + + + Enable Custom Ringtone + + + + + Connectivity + Conectare + + + + STUN Address + + + + + Use STUN + Folosește STUN + + + + Use UPnP + + + + + Use TURN + Folosește TURN + + + + TURN Password + + + + + TURN Username + + + + + TURN Address + + + + + Media + Media + + + + Enable Video + Activează Video + + + + Video Codecs + + + + + Audio Codecs + + + + + Audio Files (*.wav *.ogg *.opus *.mp3 *aiff *wma) + Fișiere Audio (*.wav *.ogg *.opus *.mp3 *aiff *wma) + + + + Add a custom ringtone + + + + + AdvancedSettingsWidget + + + Form + + + + + Call Settings + + + + + Allow Calls From Untrusted Peers + + + + + Auto Answer Calls + + + + + Enable Custom Ringtone + + + + + Add a custom ringtone + + + + + Name Server + + + + + Address + Adresă + + + + OpenDHT Configuration + + + + + Enable Proxy + + + + + Bootstrap + Pornire + + + + Security + Protecție + + + + Private Key Password + Parola cheii private + + + + User Certificate + Certificat de utilizator + + + + Private Key + + + + + CA Certificate + + + + + Connectivity + Conectare + + + + Use STUN + Folosește STUN + + + + STUN Address + + + + + Use UPnP + + + + + Use TURN + Folosește TURN + + + + TURN Password + + + + + TURN Username + + + + + TURN Address + + + + + Media + Media + + + + Enable Video + Activează Video + + + + Audio Codecs + + + + + Video Codecs + + + + + Audio Files (*.wav *.ogg *.opus *.mp3 *aiff *wma) + Fișiere Audio (*.wav *.ogg *.opus *.mp3 *aiff *wma) + + + + AnimatedOverlay + + + Form + + + + + BannedItemWidget + + + Form + + + + + name + + + + + id + + + + + CallWidget + + + Show conversations + + + + + Conversations + Conversații + + + + Search contact text input + + + + + Jami is free software for universal communication which respects the freedoms and privacy of its users. + Jami este un program liber pentru comunicare universală care respectă libertățile și intimitatea utilizatorilor săi. + + + + + This is your ID. +Copy and share it with your friends! + + + + + + Show ring ID QR code + Arată Jami ID și codul QR + + + + Share ring ID button + butonul Distribuie Jami ID + + + + Double-click to copy + + + + + Error while generating QR Code + Eroare la generarea codului QR + + + + + best name + + + + + best Id + + + + + Back to homepage button + butonul Înapoi la pagina Acasă + + + + Add to contacts + Adaugă la contacte + + + + Show invites + + + + + Invites + + + + + + Find a new or existing contact + + + + + Wants to talk to you! + + + + + Answer incoming call button + butonul Răspunde la apel + + + + Ignore incoming call button + butonul Ignoră apelul + + + + Answer + + + + + Ignore + Ignoră + + + + Cancel outgoing call + Anulează apelul efectuat + + + + Cancel + Renunță + + + + Start video call + Începe un apel video + + + + Start audio call + Începe un apel audio + + + + Clear conversation + Șterge conversația + + + + Remove contact + Șterge contactul + + + + Block contact + Blochează contactul + + + + Copy number + Copiază numărul + + + + Search your received invitations + + + + + Contact me on Jami + Contactează-mă pe Jami + + + + My Id is : + + + + + %1 + %1 is the contact username + + + + + %1 + %1 is the contact unique identifier + + + + + Call incoming from %1 + Apel primit de la %1 + + + + DeleteAccountDialog + + + Account deletion + + + + + Do you really want to delete the following account? + + + + + If this account hasn't been exported, or added to another device, it will be irrevocably lost. + + + + + Permanently delete account + + + + + Delete + Șterge + + + + Cancel account deletion + + + + + Cancel + Renunță + + + + DeviceItemWidget + + + Form + + + + + Device Id + + + + + this device + acest dispozitiv + + + + InviteButtonsWidget + + + Accept + Acceptă + + + + Refuse + Refuză + + + + Block + Blochează + + + + LinkDeviceDialog + + + Dialog + + + + + Enter your account password + + + + + Password + Parolă + + + + Ok + Ok + + + + Cancel + Renunță + + + + Exporting account + + + + + Your PIN is + Codul tău PIN e + + + + PIN + PIN + + + + This pin and the account password should be entered in your device within 10 minutes. + Acest cod PIN și parola contului trebuie introduse în dispozitiv în 10 minute. + + + + Close + Închide + + + + Link Another Device + Asociază alt dispozitiv + + + + Incorrect password + + + + + Something went wrong. +Please try again later. + + + + + MainWindow + + + Settings + Reglări + + + + Exit + + + + + About + Despre + + + + Jami + Jami + + + + NameRegistrationDialog + + + Set Registered Name + + + + + Enter your account password + + + + + Password text input + + + + + Password text entry + + + + + Password + Parolă + + + + Register + Înscrie-te + + + + Cancel + Renunță + + + + Registering Name + + + + + Something went wrong + + + + + Close + Închide + + + + Incorrect password + + + + + Network error + Eroare de rețea + + + + NewWizardWidget + + + Form + + + + + Welcome Label + + + + + Welcome to + + + + + Welcome Logo + + + + + Create Jami account button + butonul Creează un cont Jami + + + + Push button for Jami account creation start trigger + + + + + Create a Jami account + Creează un cont Jami + + + + Link device button + butonul Asociază dispozitivul + + + + Push button for device linkage start trigger + Apasă butonul pentru a începe asocierea dispozitivului + + + + Link this device to an account + Asociază acest dispozitiv unui cont + + + + Create Jami SIP account button + butonul Creează un cont Jami SIP + + + + Push button for Jami SIP account creation start trigger + + + + + Create a SIP account + + + + + Link this device to an existing account + Asociază acest dispozitiv unui cont existent + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Ubuntu'; font-size:14px; color:#555555;">To link this device to another account, you first </span><span style=" font-family:'Ubuntu'; font-size:14px; font-weight:600; color:#555555;">need to obtain a PIN</span><span style=" font-family:'Ubuntu'; font-size:14px; color:#555555;"> code. To generate the PIN code:</span></p> +<ol style="margin-top: 0px; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; -qt-list-indent: 1;"><li style=" font-family:'Ubuntu'; font-size:14px; color:#555555;" style=" margin-top:12px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:14px;">Go to the </span><span style=" font-size:14px; font-weight:600;">Account management setting</span><span style=" font-size:14px;"> of a previous device</span></li> +<li style=" font-family:'Ubuntu'; font-size:14px; color:#555555;" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:14px;">Choose the </span><span style=" font-size:14px; font-weight:600;">Jami account</span><span style=" font-size:14px;"> you want to use</span></li> +<li style=" font-family:'Ubuntu'; font-size:14px; color:#555555;" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:14px;">Go to the </span><span style=" font-size:14px; font-weight:600;">Devices</span><span style=" font-size:14px;"> tab</span></li> +<li style=" font-family:'Ubuntu'; font-size:14px; color:#555555;" style=" margin-top:0px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:14px;">Select </span><span style=" font-size:14px; font-weight:600;">Add a device</span></li></ol> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Ubuntu'; font-size:14px; color:#555555;">You will get the necessary PIN to complete this form. The PIN is only valid for </span><span style=" font-family:'Ubuntu'; font-size:14px; font-weight:600; color:#555555;">10 minutes</span><span style=" font-family:'Ubuntu'; font-size:10px; color:#555555;">.</span></p></body></html> + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Ubuntu'; font-size:14px; color:#555555;">Pentru a asocia acest dispozitiv unui alt cont, mai întîi </span><span style=" font-family:'Ubuntu'; font-size:14px; font-weight:600; color:#555555;">trebuie să obții un cod</span><span style=" font-family:'Ubuntu'; font-size:14px; color:#555555;"> PIN. Pentru a genera codul PIN:</span></p> +<ol style="margin-top: 0px; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; -qt-list-indent: 1;"><li style=" font-family:'Ubuntu'; font-size:14px; color:#555555;" style=" margin-top:12px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:14px;">Du-te la </span><span style=" font-size:14px; font-weight:600;">reglările contului</span><span style=" font-size:14px;"> în dispozitivul care conține contul</span></li> +<li style=" font-family:'Ubuntu'; font-size:14px; color:#555555;" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:14px;">Alege </span><span style=" font-size:14px; font-weight:600;">contul Jami</span><span style=" font-size:14px;"> pe care vrei să-l folosești</span></li> +<li style=" font-family:'Ubuntu'; font-size:14px; color:#555555;" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:14px;">Du-te la </span><span style=" font-size:14px; font-weight:600;">pagina</span><span style=" font-size:14px;"> Dispozitive</span></li> +<li style=" font-family:'Ubuntu'; font-size:14px; color:#555555;" style=" margin-top:0px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:14px;">Alege </span><span style=" font-size:14px; font-weight:600;">Adaugă un dispozitiv</span></li></ol> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Ubuntu'; font-size:14px; color:#555555;">Vei obține codul PIN necesar. Acest PIN e valabil doar </span><span style=" font-family:'Ubuntu'; font-size:14px; font-weight:600; color:#555555;">10 minute</span><span style=" font-family:'Ubuntu'; font-size:10px; color:#555555;">.</span></p></body></html> + + + + Enter your pin: + Introdu codul PIN: + + + + Or import a file: + Sau importă un fișier: + + + + Link from exported account archive file + Asociază din fișierul arhivei contului exportat + + + + + + (None) + (Niciunul) + + + + Password: + Parolă: + + + + + Profile + Profil + + + + + Profile name + Numele profilului + + + + Account + Cont + + + + Register your username. +This will reserve the username so that only you can use it. +Your friends will be able to call you with your usename +instead of using your ID. + + + + + Public username checkbox + + + + + Checkbox selecting if the user wants a public username + + + + + Register public username + Înregistrează numele de utilizator public + + + + Public username edit + + + + + Choose your username + + + + + Password text input + + + + + Password text entry + + + + + + Password + Parolă + + + + + Password confirmation text input + + + + + Confirm password + Confirmă parola + + + + SIP Account + + + + + SIP Server edit + + + + + Server + + + + + SIP proxy input + + + + + SIP proxy text entry + + + + + Proxy + Proxy + + + + SIP username input + + + + + SIP Password text entry + + + + + Username + Nume de Utilizator + + + + + SIP Password text input + + + + + Generating your Jami account… + Se creează contul tău Jami... + + + + Previous page button + butonul Pagina precedentă + + + + push button to access previous page of wizard + + + + + Previous + Înapoi + + + + Cancel account create/link + Renunță la crearea/asocierea contului + + + + push button to cancel account creation or linking + apasă butonul pentru a renunța la crearea sau asocierea contului + + + + Back + Înapoi + + + + Next page Button + butonul Pagina următoare + + + + Push button to access next page of wizard + + + + + Next + Următorul + + + + Open File + Deschide fișierul + + + + Jami archive files (*.gz); All files (*) + Fișierul arhivei Jami (*.gz); Toate fișierele (*) + + + + Your account needs to be migrated. Enter your password. + + + + + Migrating your Jami account... + + + + + Importing account archive... + Se importă arhiva contului... + + + + Generating your Jami account... + Se creează contul tău Jami... + + + + Generating your SIP account... + Se creează contul tău SIP... + + + + Error creating account + + + + + PasswordDialog + + + Change Account Password + + + + + Enter Current Password + + + + + Enter New Password + + + + + Confirm New Password + + + + + Confirm + + + + + Cancel + Renunță + + + + Current Password Incorrect + + + + + PhotoBoothDialog + + + Photobooth + + + + + PhotoboothWidget + + + Form + + + + + Photobooth display + + + + + Choose File + Alege fișierul + + + + Image Files (*.jpg *.jpeg *.png) + Fișiere Imagine (*.jpg *.jpeg *.png) + + + + PrivateBridging + + + Choose File + Alege fișierul + + + + Files (*) + Fișiere (*) + + + + QObject + + + No default mail client found + + + + + + Edit Device Name + + + + + Unlink Device From Account + Disociază dispozitivul de cont + + + + Save new device name + + + + + Add as contact + + + + + RingButton + + + Select folder + + + + + SettingsWidget + + + Form + + + + + Settings + Reglări + + + + Account + Cont + + + + + General + General + + + + + Audio / Video + + + + + System + Sistem + + + + Enable desktop notifications + + + + + Keep minimized on close + + + + + Download folder + Dosarul descărcării + + + + Save in + + + + + Always Recording + + + + + Updates + + + + + Check for updates automatically every + + + + + Interval between update checks in days selector + + + + + days + + + + + Check for updates now button + butonul Caută actualizări acum + + + + Check for updates now + + + + + Password + Parolă + + + + + Enable + Activează + + + + toggle enable notifications + + + + + Toggle keep minimized on close + + + + + Call Recordings + + + + + Toggle automatic updates + + + + + Jami Account + + + + + + Profile + Profil + + + + + Identity + Identitate + + + + Id + + + + + Registered name + + + + + Type here to register a username + + + + + Register + Înscrie-te + + + + Change Password + Schimbă Parola + + + + Export Account + Exportă Contul + + + + + Delete Account + + + + + Linked Devices + Dispozitive asociate + + + + Link Another Device + Asociază alt dispozitiv + + + + Banned Contacts + Contacte Blocate + + + + Format + + + + + Video device framerate selector + + + + + Preview unavailable + Previzualizare indisponibilă + + + + + Advanced Account Settings + + + + + SIP Account + + + + + Username + Nume de Utilizator + + + + Hostname + Numele serverului + + + + Proxy + Proxy + + + + Audio + Audio + + + + Microphone + + + + + Audio input device selector + + + + + Output Device + + + + + Choose the output device + + + + + Video + Video + + + + Device + Dispozitiv + + + + Video device selector + + + + + A registered name should not have any spaces and must be at least three letters long + + + + + This name is already taken + + + + + + Enter an alias + + + + + Register this name + + + + + Remove Device + + + + + Enter this account's password to confirm the removal of this device + + + + + Are you sure you wish to remove this device? + + + + + Export Account Here + + + + + Select A Folder For Your Downloads + + + + + Select A Folder For Your Recordings + + + + + VideoOverlay + + + Call on Hold + + + + + Hold / Unhold + + + + + Chat + Discuție + + + + Mute Mic + + + + + Record call + + + + + Name label + + + + + Time elapsed + + + + + 00:00 + 00:00 + + + + Hangup + + + + + Mute Video + Video fără sonor + + + + VideoView + + + Share entire screen + + + + + Share screen area + + + + + Share file + Distribuie fișierul + + + \ No newline at end of file diff --git a/translations/ring_client_windows_ru.ts b/translations/ring_client_windows_ru.ts new file mode 100644 index 00000000..1c18290c --- /dev/null +++ b/translations/ring_client_windows_ru.ts @@ -0,0 +1,1602 @@ + + + AboutDialog + + + + About + О программе + + + + about button + о кнопке  + + + + credits button + кнопка кредитов + + + + Credits + Благодарности + + + + Free as in Freedom + Свобода + + + + The Microsoft Windows client for Jami. +Jami is a secured and distributed communication software. + Клиент Jami для Microsoft Windows. +Jami – это приложение с распределённой архитектурой для безопасного общения. + + + + version + версия + + + + Created by: + Авторы проекта: + + + + Artwork by: + Дизайн: + + + + Based on the SFLPhone project + Основано на проекте SFLPhone + + + + AccountItemDelegate + + + Add Account + Добавить аккаунт + + + + AdvancedSIPSettingsWidget + + + Form + Форма + + + + Call Settings + Настройки вызовов + + + + Auto Answer Calls + Автоматически принимать входящие вызовы + + + + Enable Custom Ringtone + Использовать свою мелодию звонка + + + + Connectivity + Связь + + + + STUN Address + Адрес STUN + + + + Use STUN + Использовать STUN + + + + Use UPnP + Использовать UPnP + + + + Use TURN + Использовать TURN + + + + TURN Password + Пароль TURN + + + + TURN Username + Имя пользователя TURN + + + + TURN Address + Адрес TURN + + + + Media + Медиа + + + + Enable Video + Включить видео + + + + Video Codecs + Видео кодеки + + + + Audio Codecs + Аудио кодеки + + + + Audio Files (*.wav *.ogg *.opus *.mp3 *aiff *wma) + Аудиофайлы (*.wav *.ogg *.opus *.mp3 *aiff *wma) + + + + Add a custom ringtone + Добавить свою мелодию звонка + + + + AdvancedSettingsWidget + + + Form + Форма + + + + Call Settings + Настройки вызовов + + + + Allow Calls From Untrusted Peers + Разрешить вызовы от недоверенных участников + + + + Auto Answer Calls + Автоматически принимать входящие вызовы + + + + Enable Custom Ringtone + Использовать свою мелодию звонка + + + + Add a custom ringtone + Добавить свою мелодию звонка + + + + Name Server + Сервер имён + + + + Address + Адрес + + + + OpenDHT Configuration + Конфигурация OpenDHT + + + + Enable Proxy + Включить прокси + + + + Bootstrap + Инициализация + + + + Security + Безопасность + + + + Private Key Password + Пароль закрытого ключа + + + + User Certificate + Пользовательский Cертификат + + + + Private Key + Закрытый ключ + + + + CA Certificate + Сертификат удостоверяющего центра + + + + Connectivity + Связь + + + + Use STUN + Использовать STUN + + + + STUN Address + Адрес STUN + + + + Use UPnP + Использовать UPnP + + + + Use TURN + Использовать TURN + + + + TURN Password + Пароль TURN + + + + TURN Username + Имя пользователя TURN + + + + TURN Address + Адрес TURN + + + + Media + Медиа + + + + Enable Video + Включить видео + + + + Audio Codecs + Аудио кодеки + + + + Video Codecs + Видео кодеки + + + + Audio Files (*.wav *.ogg *.opus *.mp3 *aiff *wma) + Аудиофайлы (*.wav *.ogg *.opus *.mp3 *aiff *wma) + + + + AnimatedOverlay + + + Form + Форма + + + + BannedItemWidget + + + Form + Форма + + + + name + имя + + + + id + id + + + + CallWidget + + + Show conversations + Показать беседы + + + + Conversations + Разговоры + + + + Search contact text input + Найдите контакты текстовый ввод + + + + Jami is free software for universal communication which respects the freedoms and privacy of its users. + Jami — свободная программа для связи, уважающая свободу и конфиденциальность пользователей. + + + + + This is your ID. +Copy and share it with your friends! + + +Это ваш ID. +Скопируйте и поделитесь им с друзьями! + + + + + Show ring ID QR code + Показать Ring ID QR код + + + + Share ring ID button + кнопка Поделиться ID + + + + Double-click to copy + Двойной клик для копирования + + + + Error while generating QR Code + Ошибка при создании QR кода + + + + + best name + наилучшее имя + + + + best Id + наилучший ID + + + + Back to homepage button + Кнопка возврата на главную страницу + + + + Add to contacts + Добавить в контакты + + + + Show invites + Показать приглашения + + + + Invites + Приглашения + + + + + Find a new or existing contact + Поиск нового или существующего контакта + + + + Wants to talk to you! + Хочет поговорить с вами! + + + + Answer incoming call button + Кнопка ответа на входящий вызов + + + + Ignore incoming call button + Кнопка игнорирования входящего вызова + + + + Answer + Ответить + + + + Ignore + Игнорировать + + + + Cancel outgoing call + Отменить исходящий вызов + + + + Cancel + Отмена + + + + Start video call + Начать видеовызов + + + + Start audio call + Начать голосовой вызов + + + + Clear conversation + Очистить разговор + + + + Remove contact + Удалить контакт + + + + Block contact + Заблокировать контакт + + + + Copy number + Копировать номер + + + + Search your received invitations + Поиск по полученным приглашениям + + + + Contact me on Jami + Свяжитесь со мной в Jami + + + + My Id is : + Мой ID: + + + + %1 + %1 is the contact username + %1 + + + + %1 + %1 is the contact unique identifier + %1 + + + + Call incoming from %1 + Звонок от %1 + + + + DeleteAccountDialog + + + Account deletion + Удаление аккаунта + + + + Do you really want to delete the following account? + Вы действительно хотите удалить указанный аккаунт? + + + + If this account hasn't been exported, or added to another device, it will be irrevocably lost. + Если этот аккаунт не был экспортирован или привязан к другому устройству, он будет безвозвратно потерян + + + + Permanently delete account + Удалить аккаунт безвозвратно + + + + Delete + Удалить + + + + Cancel account deletion + Отменить удаление аккаунта + + + + Cancel + Отмена + + + + DeviceItemWidget + + + Form + Форма + + + + Device Id + Устройство ID + + + + this device + это устройство + + + + InviteButtonsWidget + + + Accept + Принять + + + + Refuse + Отказать + + + + Block + Заблокировать + + + + LinkDeviceDialog + + + Dialog + Диалог + + + + Enter your account password + Введите пароль вашего аккаунта + + + + Password + Пароль + + + + Ok + OK + + + + Cancel + Отмена + + + + Exporting account + Экспортировать аккаунт + + + + Your PIN is + Ваш PIN: + + + + PIN + PIN + + + + This pin and the account password should be entered in your device within 10 minutes. + Этот пин-код и пароль учетной записи должны быть введены на вашем устройстве в течение 10 минут. + + + + Close + Закрыть + + + + Link Another Device + Привязать другое устройство + + + + Incorrect password + Неверный пароль + + + + Something went wrong. +Please try again later. + Что-то пошло не так, повторите попытку позднее. + + + + MainWindow + + + Settings + Настройки + + + + Exit + Выход + + + + About + О программе + + + + Jami + Jami + + + + NameRegistrationDialog + + + Set Registered Name + Установить зарегистрированное имя + + + + Enter your account password + Введите пароль вашего аккаунта + + + + Password text input + Ввод текста пароля + + + + Password text entry + Ввод текста пароля + + + + Password + Пароль + + + + Register + Зарегистрировать + + + + Cancel + Отмена + + + + Registering Name + Зарегистрированное Имя + + + + Something went wrong + Что-то пошло не так. + + + + Close + Закрыть + + + + Incorrect password + Неверный пароль + + + + Network error + Ошибка сети + + + + NewWizardWidget + + + Form + Форма + + + + Welcome Label + Ярлык добро пожаловать + + + + Welcome to + Добро пожаловать в + + + + Welcome Logo + Логотип добро пожаловать + + + + Create Jami account button + Кнопка создать учётную запись Jami + + + + Push button for Jami account creation start trigger + Нажмите кнопку для запуска создания учетной записи Jami + + + + Create a Jami account + Создать учётную запись Jami + + + + Link device button + Кнопка привязки устройства + + + + Push button for device linkage start trigger + Нажмите кнопку для запуска устройства связи + + + + Link this device to an account + Привязать это устройство к аккаунту + + + + Create Jami SIP account button + Кнопка создания учётной запись Jami SIP + + + + Push button for Jami SIP account creation start trigger + Кнопка для создания начала Jami SIP триггера + + + + Create a SIP account + Создать SIP Аккаунт + + + + Link this device to an existing account + Привязать это устройство к существующему аккаунту + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Ubuntu'; font-size:14px; color:#555555;">To link this device to another account, you first </span><span style=" font-family:'Ubuntu'; font-size:14px; font-weight:600; color:#555555;">need to obtain a PIN</span><span style=" font-family:'Ubuntu'; font-size:14px; color:#555555;"> code. To generate the PIN code:</span></p> +<ol style="margin-top: 0px; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; -qt-list-indent: 1;"><li style=" font-family:'Ubuntu'; font-size:14px; color:#555555;" style=" margin-top:12px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:14px;">Go to the </span><span style=" font-size:14px; font-weight:600;">Account management setting</span><span style=" font-size:14px;"> of a previous device</span></li> +<li style=" font-family:'Ubuntu'; font-size:14px; color:#555555;" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:14px;">Choose the </span><span style=" font-size:14px; font-weight:600;">Jami account</span><span style=" font-size:14px;"> you want to use</span></li> +<li style=" font-family:'Ubuntu'; font-size:14px; color:#555555;" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:14px;">Go to the </span><span style=" font-size:14px; font-weight:600;">Devices</span><span style=" font-size:14px;"> tab</span></li> +<li style=" font-family:'Ubuntu'; font-size:14px; color:#555555;" style=" margin-top:0px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:14px;">Select </span><span style=" font-size:14px; font-weight:600;">Add a device</span></li></ol> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Ubuntu'; font-size:14px; color:#555555;">You will get the necessary PIN to complete this form. The PIN is only valid for </span><span style=" font-family:'Ubuntu'; font-size:14px; font-weight:600; color:#555555;">10 minutes</span><span style=" font-family:'Ubuntu'; font-size:10px; color:#555555;">.</span></p></body></html> + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Ubuntu'; font-size:14px; color:#555555;">Чтобы соединить это устройство с другой учетной записью, сначала</span><span style=" font-family:'Ubuntu'; font-size:14px; font-weight:600; color:#555555;">нужно получить ПИН-код</span><span style=" font-family:'Ubuntu'; font-size:14px; color:#555555;"> Чтобы сгенерировать ПИН-код:</span></p> +<ol style="margin-top: 0px; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; -qt-list-indent: 1;"><li style=" font-family:'Ubuntu'; font-size:14px; color:#555555;" style=" margin-top:12px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:14px;">Перейдите к </span><span style=" font-size:14px; font-weight:600;">настройкам управления аккаунтом</span><span style=" font-size:14px;"> предыдущего устройства </span></li> +<li style=" font-family:'Ubuntu'; font-size:14px; color:#555555;" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:14px;">Выберите </span><span style=" font-size:14px; font-weight:600;">акаунт Jami </span><span style=" font-size:14px;"> который хотите использовать</span></li> +<li style=" font-family:'Ubuntu'; font-size:14px; color:#555555;" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:14px;">Перейдите на</span><span style=" font-size:14px; font-weight:600;">вкладку устройства</span><span style=" font-size:14px;"> </span></li>выберите</span><span style=" font-size:14px; font-weight:600;">Добавить устройство</span></li></ol> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Ubuntu'; font-size:14px; color:#555555;">Вы получите необходимый ПИН-код для заполнения этой формы. ПИН действителен только </span><span style=" font-family:'Ubuntu'; font-size:14px; font-weight:600; color:#555555;">10 минут</span><span style=" font-family:'Ubuntu'; font-size:10px; color:#555555;">.</span></p></body></html> + + + + Enter your pin: + Введите ваш PIN: + + + + Or import a file: + Или импортируйте из файла: + + + + Link from exported account archive file + Привязать из архивного файла аккаунта + + + + + + (None) + (нет) + + + + Password: + Пароль: + + + + + Profile + Профиль + + + + + Profile name + Имя профиля + + + + Account + Аккаунт + + + + Register your username. +This will reserve the username so that only you can use it. +Your friends will be able to call you with your usename +instead of using your ID. + Зарегистрируйте свое имя пользователя. +После регистрации только вы сможете его использовать. Ваши друзья смогут связаться с вами по вашему имени вместо ID. + + + + Public username checkbox + Флажок публичного имени пользователя + + + + Checkbox selecting if the user wants a public username + Флажок, если пользователь хочет публичное имя пользователя + + + + Register public username + Зарегистрировать публичное имя + + + + Public username edit + Изменить публичное имя пользователя + + + + Choose your username + Выберите ваше имя пользователя + + + + Password text input + Ввод текста пароля + + + + Password text entry + Ввод текста пароля + + + + + Password + Пароль + + + + + Password confirmation text input + Ввод текста подтверждения пароля + + + + Confirm password + Подтверждение пароля + + + + SIP Account + Аккаунт SIP + + + + SIP Server edit + Изменить сервер SIP + + + + Server + Сервер + + + + SIP proxy input + Ввод SIP Прокси + + + + SIP proxy text entry + SIP прокси текстовый ввод + + + + Proxy + Прокси + + + + SIP username input + SIP ввод имени пользователя + + + + SIP Password text entry + Ввод SIP пароля + + + + Username + Имя пользователя + + + + + SIP Password text input + текстовое поле SIP + + + + Generating your Jami account… + Идёт создание вашего аккаунта Jami… + + + + Previous page button + кнопка Предыдущая страница + + + + push button to access previous page of wizard + нажмите кнопку для перехода к предыдущей странице Мастера + + + + Previous + Назад + + + + Cancel account create/link + Отмена создание/ссылки аккаунта + + + + push button to cancel account creation or linking + нажмите кнопку, чтобы отменить аккаунта или привязки + + + + Back + Назад + + + + Next page Button + Кнопка Следующая страница + + + + Push button to access next page of wizard + Нажмите кнопку для перехода к следующей странице Мастера + + + + Next + Далее + + + + Open File + Открыть файл + + + + Jami archive files (*.gz); All files (*) + Архивы Jami (*.gz); Все файлы (*) + + + + Your account needs to be migrated. Enter your password. + Ваша учетная запись должна быть перенесена. Введите ваш пароль. + + + + Migrating your Jami account... + Переносим ваш аккаунт Jami… + + + + Importing account archive... + Импорт архива с аккаунтом… + + + + Generating your Jami account... + Идёт создание вашего аккаунта Jami… + + + + Generating your SIP account... + Сгенерировать свой SIP аккаунт... + + + + Error creating account + Ошибка при создании аккаунта + + + + PasswordDialog + + + Change Account Password + Изменить пароль аккаунта + + + + Enter Current Password + Введите текущий пароль + + + + Enter New Password + Введите новый пароль + + + + Confirm New Password + Подтвердите новый пароль + + + + Confirm + Подтвердить + + + + Cancel + Отмена + + + + Current Password Incorrect + Текущий пароль неправилен + + + + PhotoBoothDialog + + + Photobooth + Фотобудка + + + + PhotoboothWidget + + + Form + Форма + + + + Photobooth display + Дисплей фото + + + + Choose File + Выберите файл + + + + Image Files (*.jpg *.jpeg *.png) + Файлы изображений (*.jpg *.jpeg *.png) + + + + PrivateBridging + + + Choose File + Выберите файл + + + + Files (*) + Файлы (*) + + + + QObject + + + No default mail client found + Не найден почтовый клиент по умолчанию + + + + + Edit Device Name + Изменить имя устройства + + + + Unlink Device From Account + Отвязать устройство от аккаунта + + + + Save new device name + Сохранить новое имя устройства + + + + Add as contact + Добавить как контакт + + + + RingButton + + + Select folder + Выбрать папку + + + + SettingsWidget + + + Form + Форма + + + + Settings + Настройки + + + + Account + Аккаунт + + + + + General + Общие + + + + + Audio / Video + Аудио/Видео + + + + System + Система + + + + Enable desktop notifications + Включить уведомления + + + + Keep minimized on close + Сворачивать вместо закрытия + + + + Download folder + Папка для загрузок + + + + Save in + Сохранить в + + + + Always Recording + Всегда записывать + + + + Updates + Обновления + + + + Check for updates automatically every + Проверять обновления автоматически каждые + + + + Interval between update checks in days selector + Интервал проверки обновлений (дней) + + + + days + дней + + + + Check for updates now button + Кнопка Проверить обновления + + + + Check for updates now + Проверить обновления + + + + Password + Пароль + + + + + Enable + Задействовать + + + + toggle enable notifications + переключатель активации уведомлений + + + + Toggle keep minimized on close + Пеоекючатель Сворачивать при закрытии + + + + Call Recordings + Записи звонков + + + + Toggle automatic updates + Переключение автоматических обновлений + + + + Jami Account + Аккаунт Jami + + + + + Profile + Профиль + + + + + Identity + Идентификатор + + + + Id + ID + + + + Registered name + Зарегистрированное имя + + + + Type here to register a username + Введите имя пользователя для регистрации + + + + Register + Зарегистрировать + + + + Change Password + Изменить пароль + + + + Export Account + Экспортировать учетную запись + + + + + Delete Account + Удалить аккаунт + + + + Linked Devices + Привязанные устройства + + + + Link Another Device + Привязать другое устройство + + + + Banned Contacts + Заблокированные контакты + + + + Format + Формат + + + + Video device framerate selector + Селектор частоты кадров видео + + + + Preview unavailable + Предпросмотр недоступен + + + + + Advanced Account Settings + Дополнительные настройки аккаунта + + + + SIP Account + Аккаунт SIP + + + + Username + Имя пользователя + + + + Hostname + Имя узла + + + + Proxy + Прокси + + + + Audio + Звук + + + + Microphone + Микрофон + + + + Audio input device selector + Выбор входного аудиоустройства + + + + Output Device + Устройство вывода + + + + Choose the output device + Выберите устройство вывода + + + + Video + Видео + + + + Device + Устройство + + + + Video device selector + Селектор видеоустройств + + + + A registered name should not have any spaces and must be at least three letters long + Зарегистрированное имя пользователя не должно содержать пробелов и быть как минимум три символа длиной + + + + This name is already taken + Это имя пользователя уже занято + + + + + Enter an alias + Введите псевдоним + + + + Register this name + Зарегистрировать новое имя + + + + Remove Device + Удалить устройство + + + + Enter this account's password to confirm the removal of this device + Введите пароль аккаунта для удаления этого устройства + + + + Are you sure you wish to remove this device? + Вы действительно хотите удалить это устройство? + + + + Export Account Here + Экспортировать аккаунт сюда + + + + Select A Folder For Your Downloads + Выберите папку для ваших загрузок + + + + Select A Folder For Your Recordings + Выберите папку для ваших записей + + + + VideoOverlay + + + Call on Hold + Звонок приостановлен + + + + Hold / Unhold + Приостановить / Возобновить + + + + Chat + Чат + + + + Mute Mic + Выключить микрофон + + + + Record call + Записать разговор + + + + Name label + Название метки + + + + Time elapsed + Прошло времени + + + + 00:00 + 00:00 + + + + Hangup + Повесить трубку + + + + Mute Video + Выключить видео + + + + VideoView + + + Share entire screen + Транслировать весь экран + + + + Share screen area + Транслировать область экрана + + + + Share file + Поделиться файлом + + + \ No newline at end of file diff --git a/translations/ring_client_windows_ru_RU.ts b/translations/ring_client_windows_ru_RU.ts new file mode 100644 index 00000000..a67fb577 --- /dev/null +++ b/translations/ring_client_windows_ru_RU.ts @@ -0,0 +1,1606 @@ + + + AboutDialog + + + + About + О программе + + + + about button + кнопка "О нас" + + + + credits button + Кнопка "создатели" + + + + Credits + Благодарности + + + + Free as in Freedom + Свобода + + + + The Microsoft Windows client for Jami. +Jami is a secured and distributed communication software. + Клиент Jami для Microsoft Windows. +Jami это защищённое и распределённое ПО для коммуникации. + + + + version + Версия + + + + Created by: + Создано: + + + + Artwork by: + Художник: + + + + Based on the SFLPhone project + Основано на SFLPhone проекте + + + + AccountItemDelegate + + + Add Account + Добавить аккаунт + + + + AdvancedSIPSettingsWidget + + + Form + Форма + + + + Call Settings + Настройки вызова + + + + Auto Answer Calls + Автоматический ответ на вызов + + + + Enable Custom Ringtone + Включить свой рингтон + + + + Connectivity + Связь + + + + STUN Address + STUN Адрес + + + + Use STUN + Использовать STUN + + + + Use UPnP + Использовать UPnP + + + + Use TURN + Использовать TURN + + + + TURN Password + TURN Пароль + + + + TURN Username + TURN Имя пользователя + + + + TURN Address + TURN Адрес + + + + Media + Медиа + + + + Enable Video + Включить видео + + + + Video Codecs + Видеокодеки + + + + Audio Codecs + Аудиокодеки + + + + Audio Files (*.wav *.ogg *.opus *.mp3 *aiff *wma) + Аудиофайлы (*.wav *.ogg *.opus *.mp3 *aiff *wma) + + + + Add a custom ringtone + Добавить свой рингтон + + + + AdvancedSettingsWidget + + + Form + Форма + + + + Call Settings + Настройки вызова + + + + Allow Calls From Untrusted Peers + Разрешить звонки из ненадёжных пиров + + + + Auto Answer Calls + Автоматический ответ на вызов + + + + Enable Custom Ringtone + Включить свой рингтон + + + + Add a custom ringtone + Добавить свой рингтон + + + + Name Server + Имя Сервера + + + + Address + Адрес + + + + OpenDHT Configuration + Конфигурация OpenDHT + + + + Enable Proxy + Включить Прокси + + + + Bootstrap + Начальная загрузка + + + + Security + Безопасность + + + + Private Key Password + Пароль закрытого ключа + + + + User Certificate + Сертификат пользователя + + + + Private Key + Приватный Ключ + + + + CA Certificate + Сертификат удостоверяющего центра + + + + Connectivity + Связь + + + + Use STUN + Использовать STUN + + + + STUN Address + STUN Адрес + + + + Use UPnP + Использовать UPnP + + + + Use TURN + Использовать TURN + + + + TURN Password + TURN Пароль + + + + TURN Username + TURN Имя пользователя + + + + TURN Address + TURN адрес + + + + Media + Медиа + + + + Enable Video + Включить видео + + + + Audio Codecs + Аудиокодеки + + + + Video Codecs + Видеокодеки + + + + Audio Files (*.wav *.ogg *.opus *.mp3 *aiff *wma) + Аудиофайлы (*.wav *.ogg *.opus *.mp3 *aiff *wma) + + + + AnimatedOverlay + + + Form + Форма + + + + BannedItemWidget + + + Form + Форма + + + + name + имя + + + + id + идентификатор + + + + CallWidget + + + Show conversations + Показать переписку + + + + Conversations + Беседы + + + + Search contact text input + Поле ввода для поиска контактов + + + + Jami is free software for universal communication which respects the freedoms and privacy of its users. + Jami — свободная программа для связи, уважающая свободу и конфиденциальность пользователей. + + + + + This is your ID. +Copy and share it with your friends! + + +Это ваш ID. +Скопируйте и поделитесь им со своими друзьями! + + + + + Show ring ID QR code + Показать ring ID QR код + + + + Share ring ID button + Кнопка Поделиться ring ID + + + + Double-click to copy + Double-click to copy + + + + Error while generating QR Code + Ошибка при генерации QR кода + + + + + best name + лучшее имя + + + + best Id + лучший Id + + + + Back to homepage button + Кнопка вернуться на главную + + + + Add to contacts + Добавить контакт + + + + Show invites + Показать приглашения + + + + Invites + Приглашения + + + + + Find a new or existing contact + Найти новый или уже существующий контакт + + + + Wants to talk to you! + Хочет поговорить с вами! + + + + Answer incoming call button + Кнопка ответа на звонок + + + + Ignore incoming call button + Кнопка сброса входящего вызова + + + + Answer + Ответ + + + + Ignore + Игнорировать + + + + Cancel outgoing call + Отменить исходящий вызов + + + + Cancel + Отмена + + + + Start video call + Начать видеозвонок + + + + Start audio call + Начать аудиозвонок + + + + Clear conversation + Очистить переписку + + + + Remove contact + Удалить контакт + + + + Block contact + Заблокировать контакт + + + + Copy number + Скопировать номер + + + + Search your received invitations + Поиск полученных приглашений + + + + Contact me on Jami + Свяжитесь со мной через Jami + + + + My Id is : + Мой Id : + + + + %1 + %1 is the contact username + %1 + + + + %1 + %1 is the contact unique identifier + %1 + + + + Call incoming from %1 + Входящий вызов от %1 + + + + DeleteAccountDialog + + + Account deletion + Удаление аккаунта + + + + Do you really want to delete the following account? + Вы действительно хотите удалить привязанный аккаунт? + + + + If this account hasn't been exported, or added to another device, it will be irrevocably lost. + Если этот аккаунт не был экспортирован или добавлен на другом устройстве, он будет безвозвратно потерян. + + + + Permanently delete account + Удалить аккаунт навсегда + + + + Delete + Удалить + + + + Cancel account deletion + Отменить удаление аккаунта + + + + Cancel + Отмена + + + + DeviceItemWidget + + + Form + Форма + + + + Device Id + Id Устройства + + + + this device + это устройство + + + + InviteButtonsWidget + + + Accept + Принять + + + + Refuse + Отказать + + + + Block + Заблокировать + + + + LinkDeviceDialog + + + Dialog + Диалог + + + + Enter your account password + Введите пароль вашего аккаунта + + + + Password + Пароль + + + + Ok + Да + + + + Cancel + Отмена + + + + Exporting account + Экспорт аккаунта + + + + Your PIN is + Ваш PIN + + + + PIN + PIN + + + + This pin and the account password should be entered in your device within 10 minutes. + Этот pin-код и пароль вашего аккаунта должны быть введены в течении 10 минут. + + + + Close + Закрыть + + + + Link Another Device + Привязать Другое Устройство + + + + Incorrect password + Неверный пароль + + + + Something went wrong. +Please try again later. + Что-то пошло не так. +Пожалуйста, попробуйте позже. + + + + MainWindow + + + Settings + Настройки + + + + Exit + Выход + + + + About + О продукте + + + + Jami + Jami + + + + NameRegistrationDialog + + + Set Registered Name + Задать Зарегистрированное Имя + + + + Enter your account password + Введите пароль вашего аккаунта + + + + Password text input + Поле ввода пароля + + + + Password text entry + Поле ввода пароля + + + + Password + Пароль + + + + Register + Зарегистрировать + + + + Cancel + Отмена + + + + Registering Name + Зарегистрировать Имя + + + + Something went wrong + Что-то пошло не так + + + + Close + Закрыть + + + + Incorrect password + Неверный пароль + + + + Network error + Ошибка сети + + + + NewWizardWidget + + + Form + Форма + + + + Welcome Label + Заголовок приветствия + + + + Welcome to + Добро пожаловать в + + + + Welcome Logo + Приветствующий логотип + + + + Create Jami account button + Создать Jami аккаунт кнопка + + + + Push button for Jami account creation start trigger + Кнопка для начала создания аккаунта Jami + + + + Create a Jami account + Создать учётную запись Jami + + + + Link device button + Кнопка привязки устройства + + + + Push button for device linkage start trigger + Кнопка для запуска триггера привязки устройства + + + + Link this device to an account + Привязать это устройство к аккаунту + + + + Create Jami SIP account button + Кнопка Создать Jami SIP аккаунт + + + + Push button for Jami SIP account creation start trigger + Кнопка для запуска запуска создания аккаунта JAMI SIP + + + + Create a SIP account + Создать SIP аккаунт + + + + Link this device to an existing account + Привязать это устройство к существующему аккаунту + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Ubuntu'; font-size:14px; color:#555555;">To link this device to another account, you first </span><span style=" font-family:'Ubuntu'; font-size:14px; font-weight:600; color:#555555;">need to obtain a PIN</span><span style=" font-family:'Ubuntu'; font-size:14px; color:#555555;"> code. To generate the PIN code:</span></p> +<ol style="margin-top: 0px; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; -qt-list-indent: 1;"><li style=" font-family:'Ubuntu'; font-size:14px; color:#555555;" style=" margin-top:12px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:14px;">Go to the </span><span style=" font-size:14px; font-weight:600;">Account management setting</span><span style=" font-size:14px;"> of a previous device</span></li> +<li style=" font-family:'Ubuntu'; font-size:14px; color:#555555;" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:14px;">Choose the </span><span style=" font-size:14px; font-weight:600;">Jami account</span><span style=" font-size:14px;"> you want to use</span></li> +<li style=" font-family:'Ubuntu'; font-size:14px; color:#555555;" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:14px;">Go to the </span><span style=" font-size:14px; font-weight:600;">Devices</span><span style=" font-size:14px;"> tab</span></li> +<li style=" font-family:'Ubuntu'; font-size:14px; color:#555555;" style=" margin-top:0px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:14px;">Select </span><span style=" font-size:14px; font-weight:600;">Add a device</span></li></ol> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Ubuntu'; font-size:14px; color:#555555;">You will get the necessary PIN to complete this form. The PIN is only valid for </span><span style=" font-family:'Ubuntu'; font-size:14px; font-weight:600; color:#555555;">10 minutes</span><span style=" font-family:'Ubuntu'; font-size:10px; color:#555555;">.</span></p></body></html> + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Ubuntu'; font-size:14px; color:#555555;">Чтобы привязать это устройство к другому аккаунту, вам нужно</span><span style=" font-family:'Ubuntu'; font-size:14px; font-weight:600; color:#555555;">получить PIN</span><span style=" font-family:'Ubuntu'; font-size:14px; color:#555555;">код. Чтобы сгенерировать PIN код нужно:</span></p> +<ol style="margin-top: 0px; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; -qt-list-indent: 1;"><li style=" font-family:'Ubuntu'; font-size:14px; color:#555555;" style=" margin-top:12px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:14px;">Перейдите </span><span style=" font-size:14px; font-weight:600;">Управление аккаунтом</span><span style=" font-size:14px;"> предыдущего устройства</span></li> +<li style=" font-family:'Ubuntu'; font-size:14px; color:#555555;" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:14px;">Выберите </span><span style=" font-size:14px; font-weight:600;">Jami аккаунт</span><span style=" font-size:14px;"> который вы хотите использовать</span></li> +<li style=" font-family:'Ubuntu'; font-size:14px; color:#555555;" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:14px;">Перейдите во </span><span style=" font-size:14px; font-weight:600;">вкладку</span><span style=" font-size:14px;">Устройства </span></li> +<li style=" font-family:'Ubuntu'; font-size:14px; color:#555555;" style=" margin-top:0px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:14px;">Выберите </span><span style=" font-size:14px; font-weight:600;">Добавить устройство</span></li></ol> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Ubuntu'; font-size:14px; color:#555555;">Вы получите необходимый PIN-код для заполнения этой формы. PIN-код действителен </span><span style=" font-family:'Ubuntu'; font-size:14px; font-weight:600; color:#555555;">10 минут</span><span style=" font-family:'Ubuntu'; font-size:10px; color:#555555;">.</span></p></body></html> + + + + Enter your pin: + Введите ваш PIN: + + + + Or import a file: + Или импортируйте из файла: + + + + Link from exported account archive file + Ссылка из экспортированного файла архива аккаунта + + + + + + (None) + (Никто) + + + + Password: + Пароль: + + + + + Profile + Профиль + + + + + Profile name + Имя профиля + + + + Account + Учётная запись + + + + Register your username. +This will reserve the username so that only you can use it. +Your friends will be able to call you with your usename +instead of using your ID. + Зарегистрируйте свое имя пользователя. +Это позволит зарезервировать имя пользователя чтобы в дальнейшем его могли использовать только вы +Ваши друзьям станет доступна возможность совершать звонки по имени пользователя +вместо использования вашего ID. + + + + Public username checkbox + Чекбокс Публичного Имя пользователя + + + + Checkbox selecting if the user wants a public username + Установите флажок, если пользователь хочет использовать общедоступное имя пользователя + + + + Register public username + Зарегистрировать общедоступное имя пользователя + + + + Public username edit + Редактирование общедоступного имени пользователя + + + + Choose your username + Выберите ваше имя пользователя + + + + Password text input + Поле ввода пароля + + + + Password text entry + Поле ввода пароля + + + + + Password + Пароль + + + + + Password confirmation text input + Поле ввода подтверждения пароля + + + + Confirm password + Подтверждение пароля + + + + SIP Account + Учетная запись SIP + + + + SIP Server edit + Изменение SIP Сервер + + + + Server + Сервер + + + + SIP proxy input + SIP прокси ввод + + + + SIP proxy text entry + SIP ввод текста прокси-сервера + + + + Proxy + Прокси + + + + SIP username input + SIP ввод имя пользователя + + + + SIP Password text entry + SIP ввод пароля + + + + Username + Имя пользователя + + + + + SIP Password text input + SIP поле ввода пароля + + + + Generating your Jami account… + Идёт создание вашего аккаунта Jami… + + + + Previous page button + Кнопка предыдущая страница + + + + push button to access previous page of wizard + нажмите кнопку, чтобы вернуться к предыдущей страницы мастера + + + + Previous + Назад + + + + Cancel account create/link + Отменить создание/ссылки аккаунта + + + + push button to cancel account creation or linking + нажмите кнопку, чтобы отменить создание аккаунта или привязки + + + + Back + Назад + + + + Next page Button + Кнопка следующая страница + + + + Push button to access next page of wizard + Нажмите кнопку, чтобы перейти к следующей страницы мастера + + + + Next + Далее + + + + Open File + Открыть файл + + + + Jami archive files (*.gz); All files (*) + Архивные файлы Jami (*.gz); Все файлы (*) + + + + Your account needs to be migrated. Enter your password. + Ваша учетная запись должна быть перенесена. Введите ваш пароль. + + + + Migrating your Jami account... + Миграция вашего Jami аккаунта... + + + + Importing account archive... + Импорт архива аккаунта... + + + + Generating your Jami account... + Генерация вашего Jami аккаунта... + + + + Generating your SIP account... + Генерация вашего SIP аккаунта... + + + + Error creating account + Ошибка создания аккаунта + + + + PasswordDialog + + + Change Account Password + Поменять Пароль Аккаунта + + + + Enter Current Password + Введите Текущий Пароль + + + + Enter New Password + Введите Новый Пароль + + + + Confirm New Password + Подтвердите Новый Пароль + + + + Confirm + Подтвердить + + + + Cancel + Отмена + + + + Current Password Incorrect + Текущий Пароль Неверный + + + + PhotoBoothDialog + + + Photobooth + Фото + + + + PhotoboothWidget + + + Form + Форма + + + + Photobooth display + Фото дисплей + + + + Choose File + Выбрать файл + + + + Image Files (*.jpg *.jpeg *.png) + Изображения (*.jpg *.jpeg *.png) + + + + PrivateBridging + + + Choose File + Выбрать файл + + + + Files (*) + Файлы (*) + + + + QObject + + + No default mail client found + Не найден почтовый клиент используемый по умолчанию + + + + + Edit Device Name + Изменить Имя Устройства + + + + Unlink Device From Account + Отвязать Устройство От Аккаунта + + + + Save new device name + Сохранить новое имя устройства + + + + Add as contact + Добавить как контакт + + + + RingButton + + + Select folder + Выбрать папку + + + + SettingsWidget + + + Form + Форма + + + + Settings + Настройки + + + + Account + Учётная запись + + + + + General + Основные + + + + + Audio / Video + Аудио / Видео + + + + System + Система + + + + Enable desktop notifications + Включить уведомления на рабочем столе + + + + Keep minimized on close + Оставлять свернутым при закрытии + + + + Download folder + Папка для загрузок + + + + Save in + Сохранить в + + + + Always Recording + Всегда записывать + + + + Updates + Обновления + + + + Check for updates automatically every + Проверять обновления каждые + + + + Interval between update checks in days selector + Селектор Интервал между проверками обновлений в днях + + + + days + дней + + + + Check for updates now button + Кнопка для проверки обновлений + + + + Check for updates now + Проверить наличие обновлений + + + + Password + Пароль + + + + + Enable + Включить + + + + toggle enable notifications + Переключатель включить уведомлений + + + + Toggle keep minimized on close + Переключатель свернуть или закрыть + + + + Call Recordings + Записи вызовов + + + + Toggle automatic updates + Переключение автоматического обновления + + + + Jami Account + Jami Аккаунт + + + + + Profile + Профиль + + + + + Identity + Идентичность + + + + Id + Идентификатор + + + + Registered name + Зарегистрированное имя + + + + Type here to register a username + Напишите здесь чтобы зарегистрировать имя пользователя + + + + Register + Зарегистрировать + + + + Change Password + Изменить Пароль + + + + Export Account + Экспортировать Аккаунт + + + + + Delete Account + Удалить Аккаунт + + + + Linked Devices + Привязанные Устройства + + + + Link Another Device + Привязать Другое Устройство + + + + Banned Contacts + Заблокированные Контакты + + + + Format + Формат + + + + Video device framerate selector + Селектор частоты кадров видеоустройства + + + + Preview unavailable + Предварительный просмотр недоступен + + + + + Advanced Account Settings + Дополнительные Настройки Аккаунта + + + + SIP Account + Учетная запись SIP + + + + Username + Имя пользователя + + + + Hostname + Имя компьютера + + + + Proxy + Прокси + + + + Audio + Звук + + + + Microphone + Микрофон + + + + Audio input device selector + Селектор устройства аудиовхода + + + + Output Device + Устройства Вывода + + + + Choose the output device + Выбрать устройство вывода + + + + Video + Видео + + + + Device + Устройство + + + + Video device selector + Селектор видеоустройств + + + + A registered name should not have any spaces and must be at least three letters long + Зарегистрированное имя не должно содержать пробелов и должно иметь не менее трех букв + + + + This name is already taken + Это имя уже занято + + + + + Enter an alias + Введите псевдоним + + + + Register this name + Зарегистрировать это имя + + + + Remove Device + Удалить устройство + + + + Enter this account's password to confirm the removal of this device + Введите пароль вашего аккаунта чтобы подтвердить его удаление из устройства. + + + + Are you sure you wish to remove this device? + Вы уверены, что хотите удалить это устройство? + + + + Export Account Here + Экспортировать Аккаунт + + + + Select A Folder For Your Downloads + Выберите папку для загрузок + + + + Select A Folder For Your Recordings + Выберите Папку Для Ваших Записей + + + + VideoOverlay + + + Call on Hold + Вызов на удержании + + + + Hold / Unhold + Удерживание / Возврат + + + + Chat + Чат + + + + Mute Mic + Отключить микрофон + + + + Record call + Записывать звонок + + + + Name label + Имя метки + + + + Time elapsed + Прошедшее время + + + + 00:00 + 00:00 + + + + Hangup + Разъединить + + + + Mute Video + Громкость видео + + + + VideoView + + + Share entire screen + Транслировать весь экран + + + + Share screen area + Общий доступ к экрану + + + + Share file + Поделится файлом + + + \ No newline at end of file diff --git a/translations/ring_client_windows_sk_SK.ts b/translations/ring_client_windows_sk_SK.ts new file mode 100644 index 00000000..c7f2a9b9 --- /dev/null +++ b/translations/ring_client_windows_sk_SK.ts @@ -0,0 +1,1606 @@ + + + AboutDialog + + + + About + O programe + + + + about button + tlačidlo o programe + + + + credits button + tlačidlo autori + + + + Credits + Autori + + + + Free as in Freedom + Free as in Freedom + + + + The Microsoft Windows client for Jami. +Jami is a secured and distributed communication software. + Microsoft Windows klient pre Jami. +Jami je zabezpečený a distribuovaný komunikačný softvér. + + + + version + verzia + + + + Created by: + Vytvorili: + + + + Artwork by: + Dizajn od: + + + + Based on the SFLPhone project + Založené na projekte SFLPhone + + + + AccountItemDelegate + + + Add Account + Pridať účet + + + + AdvancedSIPSettingsWidget + + + Form + Form + + + + Call Settings + Nastavenia hovoru + + + + Auto Answer Calls + Automaticky zdvihnúť hovory + + + + Enable Custom Ringtone + Povoliť vlastné vyzváňacie tóny + + + + Connectivity + Pripojenia + + + + STUN Address + STUN adresa + + + + Use STUN + Použiť STUN + + + + Use UPnP + Používať UPnP + + + + Use TURN + Použiť TURN + + + + TURN Password + TURN heslo + + + + TURN Username + TURN používateľské meno + + + + TURN Address + TURN adresa + + + + Media + Médiá + + + + Enable Video + Povoliť video + + + + Video Codecs + Video kodeky + + + + Audio Codecs + Zvukové kodeky + + + + Audio Files (*.wav *.ogg *.opus *.mp3 *aiff *wma) + Audio súbory (*.wav *.ogg *.opus *.mp3 *aiff *wma) + + + + Add a custom ringtone + Pridať vlastný vyzváňací tón + + + + AdvancedSettingsWidget + + + Form + Formulár + + + + Call Settings + Nastavenia hovoru + + + + Allow Calls From Untrusted Peers + Povoliť hovory od nedôveryhodných peerov + + + + Auto Answer Calls + Automaticky zdvihnúť hovory + + + + Enable Custom Ringtone + Povoliť vlastné vyzváňacie tóny + + + + Add a custom ringtone + Pridať vlastný vyzváňací tón + + + + Name Server + Name server + + + + Address + Adresa + + + + OpenDHT Configuration + Konfigurácia OpenDHT + + + + Enable Proxy + Povoliť proxy + + + + Bootstrap + Bootstrap + + + + Security + Bezpečnosť + + + + Private Key Password + Heslo privátneho kľúča + + + + User Certificate + Používateľský certifikát + + + + Private Key + Privátny kľúč + + + + CA Certificate + CA certifikát + + + + Connectivity + Pripojenie + + + + Use STUN + Použiť STUN + + + + STUN Address + STUN adresa + + + + Use UPnP + Používať UPnP + + + + Use TURN + Použiť TURN + + + + TURN Password + TURN heslo + + + + TURN Username + TURN používateľské meno + + + + TURN Address + TURN adresa + + + + Media + Médiá + + + + Enable Video + Zapnúť video + + + + Audio Codecs + Zvukové kodeky + + + + Video Codecs + Video kodeky + + + + Audio Files (*.wav *.ogg *.opus *.mp3 *aiff *wma) + Audio súbory (*.wav *.ogg *.opus *.mp3 *aiff *wma) + + + + AnimatedOverlay + + + Form + Formulár + + + + BannedItemWidget + + + Form + Form + + + + name + meno + + + + id + id + + + + CallWidget + + + Show conversations + Zobraziť konverzácie + + + + Conversations + Konverzácie + + + + Search contact text input + Vstupné pole Hľadať v kontaktoch + + + + Jami is free software for universal communication which respects the freedoms and privacy of its users. + Jami je slobodný softvér na univerzálnu komunikáciu, ktorý rešpektuje slobodu a súkromie používateľov. + + + + + This is your ID. +Copy and share it with your friends! + + + Toto je vaše ID. +Skopírujte a zdieľajte ho s vašimi priateľmi! + + + + + Show ring ID QR code + Zobraziť RingID QR kód + + + + Share ring ID button + zdieľať RingID tlačidlo + + + + Double-click to copy + Dvojklik na kopírovanie + + + + Error while generating QR Code + Chyba pri generovaní QR kódu + + + + + best name + najlepšie meno + + + + best Id + najlepšie id + + + + Back to homepage button + Tlačidlo Späť domov + + + + Add to contacts + Pridať do kontaktov + + + + Show invites + Zobraziť pozvánky + + + + Invites + Pozvánky + + + + + Find a new or existing contact + Vyhľadať nový alebo existujúci kontakt + + + + Wants to talk to you! + Chce s vami hovoriť! + + + + Answer incoming call button + Tlačidlo Zdvihnúť prichádzajúci hovor + + + + Ignore incoming call button + Tlačidlo Ignorovať prichádzajúci hovor + + + + Answer + Zdvihnúť + + + + Ignore + Ignorovať + + + + Cancel outgoing call + Zrušiť odchádzajúci hovor + + + + Cancel + Zrušiť + + + + Start video call + Začať video hovor + + + + Start audio call + Začať audio hovor + + + + Clear conversation + Vymazať konverzáciu + + + + Remove contact + Odstrániť kontakt + + + + Block contact + Zablokovať kontakt + + + + Copy number + Skopírovať číslo + + + + Search your received invitations + Prehľadávať prijaté pozvánky + + + + Contact me on Jami + Kontaktujte ma na Jami + + + + My Id is : + Moje ID je: + + + + %1 + %1 is the contact username + %1 + + + + %1 + %1 is the contact unique identifier + %1 + + + + Call incoming from %1 + Prichádzajúci hovor od %1 + + + + DeleteAccountDialog + + + Account deletion + Odstraňovanie účtu + + + + Do you really want to delete the following account? + Určite chcete odstrániť nasledujúci účet? + + + + If this account hasn't been exported, or added to another device, it will be irrevocably lost. + Ak tento účet nebol exportovaný alebo pridaný k inému zariadeniu, bude nenávratne stratený. + + + + Permanently delete account + Permanentne odstrániť účet + + + + Delete + Vymazať + + + + Cancel account deletion + Zrušiť odstraňovanie účtu + + + + Cancel + Zrušiť + + + + DeviceItemWidget + + + Form + Form + + + + Device Id + Id zariadenia + + + + this device + toto zariadenie + + + + InviteButtonsWidget + + + Accept + Prijať + + + + Refuse + Odmietnuť + + + + Block + Blokovať + + + + LinkDeviceDialog + + + Dialog + Dialog + + + + Enter your account password + Zadajte heslo k účtu + + + + Password + Heslo + + + + Ok + OK + + + + Cancel + Zrušiť + + + + Exporting account + Exportovanie účtu + + + + Your PIN is + Váš PIN je + + + + PIN + PIN + + + + This pin and the account password should be entered in your device within 10 minutes. + Tento PIN a heslo k účtu musia byť zadané na vašom zariadení v priebehu 10 minút. + + + + Close + Zavrieť + + + + Link Another Device + Prepojiť ďalšie zariadenie + + + + Incorrect password + Nesprávne heslo + + + + Something went wrong. +Please try again later. + Došlo k chybe. +Skúste prosím neskôr. + + + + MainWindow + + + Settings + Nastavenia + + + + Exit + Odísť + + + + About + O programe + + + + Jami + Jami + + + + NameRegistrationDialog + + + Set Registered Name + Nastaviť registrované meno + + + + Enter your account password + Zadajte heslo k účtu + + + + Password text input + Textové pole na zadanie hesla + + + + Password text entry + Heslo + + + + Password + Heslo + + + + Register + Registrovať + + + + Cancel + Zrušiť + + + + Registering Name + Meno sa registruje + + + + Something went wrong + Došlo k chybe + + + + Close + Zavrieť + + + + Incorrect password + Nesprávne heslo + + + + Network error + Chyba siete + + + + NewWizardWidget + + + Form + Formulár + + + + Welcome Label + Popis Vitajte + + + + Welcome to + Vitajte v + + + + Welcome Logo + Vitajte Logo + + + + Create Jami account button + Tlačidlo Vytvoriť Jami účet + + + + Push button for Jami account creation start trigger + Push button for Jami account creation start trigger + + + + Create a Jami account + Vytvoriť Jami účet + + + + Link device button + Tlačidlo Prepojiť zariadenie + + + + Push button for device linkage start trigger + Push button for device linkage start trigger + + + + Link this device to an account + Prepojiť toto zariadenie s účtom + + + + Create Jami SIP account button + Tlačidlo Vytvoriť Jami SIP účet + + + + Push button for Jami SIP account creation start trigger + Stlačte tlačidlo na spustenie vytvorenia Jami SIP účtu + + + + Create a SIP account + Vytvoriť SIP účet + + + + Link this device to an existing account + Prepojiť toto zariadenie s existujúcim účtom + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Ubuntu'; font-size:14px; color:#555555;">To link this device to another account, you first </span><span style=" font-family:'Ubuntu'; font-size:14px; font-weight:600; color:#555555;">need to obtain a PIN</span><span style=" font-family:'Ubuntu'; font-size:14px; color:#555555;"> code. To generate the PIN code:</span></p> +<ol style="margin-top: 0px; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; -qt-list-indent: 1;"><li style=" font-family:'Ubuntu'; font-size:14px; color:#555555;" style=" margin-top:12px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:14px;">Go to the </span><span style=" font-size:14px; font-weight:600;">Account management setting</span><span style=" font-size:14px;"> of a previous device</span></li> +<li style=" font-family:'Ubuntu'; font-size:14px; color:#555555;" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:14px;">Choose the </span><span style=" font-size:14px; font-weight:600;">Jami account</span><span style=" font-size:14px;"> you want to use</span></li> +<li style=" font-family:'Ubuntu'; font-size:14px; color:#555555;" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:14px;">Go to the </span><span style=" font-size:14px; font-weight:600;">Devices</span><span style=" font-size:14px;"> tab</span></li> +<li style=" font-family:'Ubuntu'; font-size:14px; color:#555555;" style=" margin-top:0px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:14px;">Select </span><span style=" font-size:14px; font-weight:600;">Add a device</span></li></ol> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Ubuntu'; font-size:14px; color:#555555;">You will get the necessary PIN to complete this form. The PIN is only valid for </span><span style=" font-family:'Ubuntu'; font-size:14px; font-weight:600; color:#555555;">10 minutes</span><span style=" font-family:'Ubuntu'; font-size:10px; color:#555555;">.</span></p></body></html> + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Ubuntu'; font-size:14px; color:#555555;">Na prepojenie zariadenia s účtom musíte najprv </span><span style=" font-family:'Ubuntu'; font-size:14px; font-weight:600; color:#555555;">získať PIN</span><span style=" font-family:'Ubuntu'; font-size:14px; color:#555555;"> kód. Na jeho vygenerovanie:</span></p> +<ol style="margin-top: 0px; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; -qt-list-indent: 1;"><li style=" font-family:'Ubuntu'; font-size:14px; color:#555555;" style=" margin-top:12px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:14px;">Choďte do </span><span style=" font-size:14px; font-weight:600;">Nastavení účtu</span><span style=" font-size:14px;"> na predchádzajúcom zariadení</span></li> +<li style=" font-family:'Ubuntu'; font-size:14px; color:#555555;" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:14px;">Zvoľte </span><span style=" font-size:14px; font-weight:600;">Jami účet,</span><span style=" font-size:14px;"> ktorý chcete použiť</span></li> +<li style=" font-family:'Ubuntu'; font-size:14px; color:#555555;" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:14px;">Choďte do </span><span style=" font-size:14px; font-weight:600;">Zariadenia</span><span style=" font-size:14px;"> záložky</span></li> +<li style=" font-family:'Ubuntu'; font-size:14px; color:#555555;" style=" margin-top:0px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:14px;">Zvoľte </span><span style=" font-size:14px; font-weight:600;">Pridať zariadenie</span></li></ol> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Ubuntu'; font-size:14px; color:#555555;">Tak získate PIN kód na dokončenie vyplnenie formuláru. Bude platný </span><span style=" font-family:'Ubuntu'; font-size:14px; font-weight:600; color:#555555;">10 minút</span><span style=" font-family:'Ubuntu'; font-size:10px; color:#555555;">.</span></p></body></html> + + + + Enter your pin: + Zadajte váš PIN: + + + + Or import a file: + Alebo importujte súbor: + + + + Link from exported account archive file + Prepojiť pomocou exportovaného archívu účtu + + + + + + (None) + (Žiadny) + + + + Password: + Heslo: + + + + + Profile + Profil + + + + + Profile name + Profilové meno + + + + Account + Účet + + + + Register your username. +This will reserve the username so that only you can use it. +Your friends will be able to call you with your usename +instead of using your ID. + Zaregistrujte si svoje používateľské meno. +Tým bude toto meno rezervované a iba vy ho budete môcť používať. +Vaši priatelia ho budú môcť použiť namiesto vášho ID, +keď vám budú chcieť zavolať. + + + + Public username checkbox + Zaškrtávacie políčko pre verejné používateľské meno + + + + Checkbox selecting if the user wants a public username + Zaškrtávacie políčko na výber toho, či používateľ chce verejné používateľské meno + + + + Register public username + Registrovať verejné používateľské meno + + + + Public username edit + Upravenie verejného používateľského mena + + + + Choose your username + Zvoľte si používateľské meno + + + + Password text input + Textové pole na zadanie hesla + + + + Password text entry + Heslo + + + + + Password + Heslo + + + + + Password confirmation text input + Textové pole na potvrdenie hesla + + + + Confirm password + Potvrďte heslo + + + + SIP Account + SIP Účet + + + + SIP Server edit + SIP server úprava + + + + Server + Server + + + + SIP proxy input + Textové pole SIP proxy + + + + SIP proxy text entry + SIP proxy + + + + Proxy + Proxy + + + + SIP username input + Vstup pre SIP používateľské meno + + + + SIP Password text entry + SIP heslo + + + + Username + Používateľské meno + + + + + SIP Password text input + Textové pole na zadanie SIP hesla + + + + Generating your Jami account… + Generovanie vášho Jami účtu... + + + + Previous page button + Tlačidlo Predchádzajúca strana + + + + push button to access previous page of wizard + stlačiť tlačidlo na návrat na predchádzajúcu stranu + + + + Previous + Predchádzajúci + + + + Cancel account create/link + Zrušiť vytváranie/prepájanie účtu + + + + push button to cancel account creation or linking + push button to cancel account creation or linking + + + + Back + Späť + + + + Next page Button + Tlačidlo Ďalšia strana + + + + Push button to access next page of wizard + Stlačte tlačidlo na prechod na ďalšiu stranu nastavenia + + + + Next + Ďalej + + + + Open File + Otvoriť súbor + + + + Jami archive files (*.gz); All files (*) + Súbory s Jami archívmi (*.gz); Všetky súbory (*) + + + + Your account needs to be migrated. Enter your password. + Váš účet musí byť migrovaný. Zadajte vaše heslo. + + + + Migrating your Jami account... + Migrovanie vášho Jami účtu... + + + + Importing account archive... + Importuje sa archív s účtom + + + + Generating your Jami account... + Generovanie vášho Jami účtu... + + + + Generating your SIP account... + Váš SIP účet sa generuje... + + + + Error creating account + Chyba pri vytváraní účtu + + + + PasswordDialog + + + Change Account Password + Zmeniť heslo účtu + + + + Enter Current Password + Zadajte súčasné heslo + + + + Enter New Password + Zadajte nové heslo + + + + Confirm New Password + Potvrďte nové heslo + + + + Confirm + Potvrdiť + + + + Cancel + Zrušiť + + + + Current Password Incorrect + Nesprávne súčasné heslo + + + + PhotoBoothDialog + + + Photobooth + Fotobúdka + + + + PhotoboothWidget + + + Form + Form + + + + Photobooth display + Displej fotobúdky + + + + Choose File + Vyberte súbor + + + + Image Files (*.jpg *.jpeg *.png) + Obrazové súbory (*.jpg *.jpeg *.png) + + + + PrivateBridging + + + Choose File + Vyberte súbor + + + + Files (*) + Súbory (*) + + + + QObject + + + No default mail client found + Nebol nájdený predvolený emailový klient + + + + + Edit Device Name + Upraviť názov zariadenia + + + + Unlink Device From Account + Zrušiť prepojenie zariadenia s účtom + + + + Save new device name + Uložiť nový názov zariadenia + + + + Add as contact + Pridať ako kontakt + + + + RingButton + + + Select folder + Vybrať priečinok + + + + SettingsWidget + + + Form + Formulár + + + + Settings + Nastavenia + + + + Account + Účet + + + + + General + Všeobecné + + + + + Audio / Video + Audio / Video + + + + System + Systém + + + + Enable desktop notifications + Povoliť desktopové notifikácie + + + + Keep minimized on close + Ponechať minimalizované namiesto vypnutia + + + + Download folder + Priečinok na stiahnutie + + + + Save in + Uložiť v + + + + Always Recording + Neustále zaznamenávanie + + + + Updates + Aktualizácie + + + + Check for updates automatically every + Skontrolovať aktualizácie automaticky s frekvenciou + + + + Interval between update checks in days selector + Prepínač pre Interval na kontrolu aktualizácií v dňoch + + + + days + dni + + + + Check for updates now button + Tlačidlo Skontrolovať aktualizácie + + + + Check for updates now + Skontrolovať aktualizácie + + + + Password + Heslo + + + + + Enable + Povoliť + + + + toggle enable notifications + prepnúť povolenie upozornení + + + + Toggle keep minimized on close + Prepnúť ponechanie minimalizovania pri zatvorení + + + + Call Recordings + Nahrávky hovorov + + + + Toggle automatic updates + Prepnúť automatické aktualizácie + + + + Jami Account + Jami účet + + + + + Profile + Profil + + + + + Identity + Identita + + + + Id + Id + + + + Registered name + Registrované meno + + + + Type here to register a username + Pre zaregistrovanie používateľského mena píšte + + + + Register + Registrovať + + + + Change Password + Zmeniť heslo + + + + Export Account + Exportovať účet + + + + + Delete Account + Odstrániť účet + + + + Linked Devices + Prepojené zariadenia + + + + Link Another Device + Prepojiť ďalšie zariadenie + + + + Banned Contacts + Blokované kontakty + + + + Format + Formát + + + + Video device framerate selector + Výber frameratu video zariadenia + + + + Preview unavailable + Náhľad nedostupný + + + + + Advanced Account Settings + Pokročilé nastavenia účtu + + + + SIP Account + SIP Účet + + + + Username + Používateľské meno + + + + Hostname + Názov hostiteľa + + + + Proxy + Proxy + + + + Audio + Zvuk + + + + Microphone + Mikrofón + + + + Audio input device selector + Volič Zvukového vstupného zariadenia + + + + Output Device + Výstupné zariadenie + + + + Choose the output device + Zvoliť výstupné zariadenie + + + + Video + Video + + + + Device + Zariadenie + + + + Video device selector + Prepínač video zariadenia + + + + A registered name should not have any spaces and must be at least three letters long + Registrované meno by nemalo obsahovať medzery a malo by byť aspoň tri znaky dlhé + + + + This name is already taken + Toto meno už je použité + + + + + Enter an alias + Zadajte alias + + + + Register this name + Registrovať toto meno + + + + Remove Device + Odstrániť zariadenie + + + + Enter this account's password to confirm the removal of this device + Potvrďte odobranie tohto zariadenia zadaním hesla zariadenia + + + + Are you sure you wish to remove this device? + Naozaj chcete odstrániť toto zariadenie? + + + + Export Account Here + Exportovať účet sem + + + + Select A Folder For Your Downloads + Zvoľte priečinok pre sťahovanie súborov + + + + Select A Folder For Your Recordings + Zvoľte priečinok pre vaše nahrávky + + + + VideoOverlay + + + Call on Hold + Volať počas podržania + + + + Hold / Unhold + Podržať / Zrušiť podržanie + + + + Chat + Chat + + + + Mute Mic + Stlmiť mikrofón + + + + Record call + Zaznamenať hovor + + + + Name label + Menovka + + + + Time elapsed + Uplynutý čas + + + + 00:00 + 00:00 + + + + Hangup + Zložiť + + + + Mute Video + Stlmiť video + + + + VideoView + + + Share entire screen + Zdieľať celú obrazovku + + + + Share screen area + Zdieľať oblasť obrazovky + + + + Share file + Zdieľať súbor + + + \ No newline at end of file diff --git a/translations/ring_client_windows_sl.ts b/translations/ring_client_windows_sl.ts new file mode 100644 index 00000000..06f61c24 --- /dev/null +++ b/translations/ring_client_windows_sl.ts @@ -0,0 +1,1589 @@ + + + AboutDialog + + + + About + O Ring + + + + about button + + + + + credits button + + + + + Credits + Zasluge + + + + Free as in Freedom + + + + + The Microsoft Windows client for Jami. +Jami is a secured and distributed communication software. + + + + + version + različica + + + + Created by: + Ustvarjalci: + + + + Artwork by: + Grafična podoba: + + + + Based on the SFLPhone project + Osnovano na projeku SFLPhone + + + + AccountItemDelegate + + + Add Account + + + + + AdvancedSIPSettingsWidget + + + Form + Obrazec + + + + Call Settings + + + + + Auto Answer Calls + + + + + Enable Custom Ringtone + + + + + Connectivity + Povezljivost + + + + STUN Address + + + + + Use STUN + Uporabi STUN + + + + Use UPnP + + + + + Use TURN + Uporabi TURN + + + + TURN Password + + + + + TURN Username + + + + + TURN Address + + + + + Media + Vsebine + + + + Enable Video + Omogoči video + + + + Video Codecs + Video kodeki + + + + Audio Codecs + Avdio kodeki + + + + Audio Files (*.wav *.ogg *.opus *.mp3 *aiff *wma) + + + + + Add a custom ringtone + + + + + AdvancedSettingsWidget + + + Form + Obrazec + + + + Call Settings + + + + + Allow Calls From Untrusted Peers + + + + + Auto Answer Calls + + + + + Enable Custom Ringtone + + + + + Add a custom ringtone + + + + + Name Server + + + + + Address + Naslov + + + + OpenDHT Configuration + + + + + Enable Proxy + + + + + Bootstrap + + + + + Security + Varnost + + + + Private Key Password + Geslo osebnega ključa + + + + User Certificate + + + + + Private Key + + + + + CA Certificate + + + + + Connectivity + Povezljivost + + + + Use STUN + Uporabi STUN + + + + STUN Address + + + + + Use UPnP + + + + + Use TURN + Uporabi TURN + + + + TURN Password + + + + + TURN Username + + + + + TURN Address + + + + + Media + Vsebine + + + + Enable Video + Omogoči video + + + + Audio Codecs + Avdio kodeki + + + + Video Codecs + Video kodeki + + + + Audio Files (*.wav *.ogg *.opus *.mp3 *aiff *wma) + + + + + AnimatedOverlay + + + Form + Obrazec + + + + BannedItemWidget + + + Form + Obrazec + + + + name + + + + + id + + + + + CallWidget + + + Show conversations + + + + + Conversations + Pogovori + + + + Search contact text input + + + + + Jami is free software for universal communication which respects the freedoms and privacy of its users. + + + + + + This is your ID. +Copy and share it with your friends! + + + + + + Show ring ID QR code + + + + + Share ring ID button + + + + + Double-click to copy + Kopiraj z dvojnim klikom + + + + Error while generating QR Code + Napaka med pripravo QR kode + + + + + best name + + + + + best Id + + + + + Back to homepage button + + + + + Add to contacts + Dodaj v stike + + + + Show invites + + + + + Invites + + + + + + Find a new or existing contact + + + + + Wants to talk to you! + Želi govoriti s tabo! + + + + Answer incoming call button + + + + + Ignore incoming call button + + + + + Answer + Odgovori + + + + Ignore + Ignoriraj + + + + Cancel outgoing call + + + + + Cancel + Prekliči + + + + Start video call + + + + + Start audio call + + + + + Clear conversation + + + + + Remove contact + Odstrani stik + + + + Block contact + + + + + Copy number + Kopiraj številko + + + + Search your received invitations + + + + + Contact me on Jami + + + + + My Id is : + + + + + %1 + %1 is the contact username + %1 + + + + %1 + %1 is the contact unique identifier + %1 + + + + Call incoming from %1 + Dohodni klic od %1 + + + + DeleteAccountDialog + + + Account deletion + + + + + Do you really want to delete the following account? + + + + + If this account hasn't been exported, or added to another device, it will be irrevocably lost. + + + + + Permanently delete account + + + + + Delete + Pobriši + + + + Cancel account deletion + + + + + Cancel + Prekliči + + + + DeviceItemWidget + + + Form + Obrazec + + + + Device Id + + + + + this device + ta naprava + + + + InviteButtonsWidget + + + Accept + Sprejmi + + + + Refuse + Zavrni + + + + Block + Blokiraj + + + + LinkDeviceDialog + + + Dialog + + + + + Enter your account password + + + + + Password + Geslo + + + + Ok + V redu + + + + Cancel + Prekliči + + + + Exporting account + + + + + Your PIN is + + + + + PIN + PIN + + + + This pin and the account password should be entered in your device within 10 minutes. + + + + + Close + Zapri + + + + Link Another Device + + + + + Incorrect password + + + + + Something went wrong. +Please try again later. + + + + + MainWindow + + + Settings + Nastavitve + + + + Exit + Izhod + + + + About + O Ring + + + + Jami + + + + + NameRegistrationDialog + + + Set Registered Name + + + + + Enter your account password + + + + + Password text input + + + + + Password text entry + + + + + Password + Geslo + + + + Register + Prijavi se + + + + Cancel + Prekliči + + + + Registering Name + + + + + Something went wrong + + + + + Close + Zapri + + + + Incorrect password + + + + + Network error + Napaka mreže + + + + NewWizardWidget + + + Form + Obrazec + + + + Welcome Label + + + + + Welcome to + Dobrodošli v + + + + Welcome Logo + + + + + Create Jami account button + + + + + Push button for Jami account creation start trigger + + + + + Create a Jami account + + + + + Link device button + + + + + Push button for device linkage start trigger + + + + + Link this device to an account + Poveži to napravo k računu + + + + Create Jami SIP account button + + + + + Push button for Jami SIP account creation start trigger + + + + + Create a SIP account + + + + + Link this device to an existing account + Poveži to napravo k obstoječemu računu + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Ubuntu'; font-size:14px; color:#555555;">To link this device to another account, you first </span><span style=" font-family:'Ubuntu'; font-size:14px; font-weight:600; color:#555555;">need to obtain a PIN</span><span style=" font-family:'Ubuntu'; font-size:14px; color:#555555;"> code. To generate the PIN code:</span></p> +<ol style="margin-top: 0px; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; -qt-list-indent: 1;"><li style=" font-family:'Ubuntu'; font-size:14px; color:#555555;" style=" margin-top:12px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:14px;">Go to the </span><span style=" font-size:14px; font-weight:600;">Account management setting</span><span style=" font-size:14px;"> of a previous device</span></li> +<li style=" font-family:'Ubuntu'; font-size:14px; color:#555555;" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:14px;">Choose the </span><span style=" font-size:14px; font-weight:600;">Jami account</span><span style=" font-size:14px;"> you want to use</span></li> +<li style=" font-family:'Ubuntu'; font-size:14px; color:#555555;" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:14px;">Go to the </span><span style=" font-size:14px; font-weight:600;">Devices</span><span style=" font-size:14px;"> tab</span></li> +<li style=" font-family:'Ubuntu'; font-size:14px; color:#555555;" style=" margin-top:0px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:14px;">Select </span><span style=" font-size:14px; font-weight:600;">Add a device</span></li></ol> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Ubuntu'; font-size:14px; color:#555555;">You will get the necessary PIN to complete this form. The PIN is only valid for </span><span style=" font-family:'Ubuntu'; font-size:14px; font-weight:600; color:#555555;">10 minutes</span><span style=" font-family:'Ubuntu'; font-size:10px; color:#555555;">.</span></p></body></html> + + + + + Enter your pin: + Vnesi svoj PIN: + + + + Or import a file: + + + + + Link from exported account archive file + + + + + + + (None) + + + + + Password: + + + + + + Profile + Profil + + + + + Profile name + + + + + Account + Račun + + + + Register your username. +This will reserve the username so that only you can use it. +Your friends will be able to call you with your usename +instead of using your ID. + + + + + Public username checkbox + + + + + Checkbox selecting if the user wants a public username + + + + + Register public username + Prijavi javno ime + + + + Public username edit + + + + + Choose your username + Izberi svoje uporabniško ime: + + + + Password text input + + + + + Password text entry + + + + + + Password + Geslo + + + + + Password confirmation text input + + + + + Confirm password + Potrdi geslo + + + + SIP Account + SIP račun + + + + SIP Server edit + + + + + Server + + + + + SIP proxy input + + + + + SIP proxy text entry + + + + + Proxy + Proxy + + + + SIP username input + + + + + SIP Password text entry + + + + + Username + Uporabnik + + + + + SIP Password text input + + + + + Generating your Jami account… + + + + + Previous page button + + + + + push button to access previous page of wizard + + + + + Previous + Prejšni + + + + Cancel account create/link + + + + + push button to cancel account creation or linking + + + + + Back + Nazaj + + + + Next page Button + + + + + Push button to access next page of wizard + + + + + Next + Naprej + + + + Open File + Odpri datoteko + + + + Jami archive files (*.gz); All files (*) + + + + + Your account needs to be migrated. Enter your password. + + + + + Migrating your Jami account... + + + + + Importing account archive... + + + + + Generating your Jami account... + + + + + Generating your SIP account... + + + + + Error creating account + + + + + PasswordDialog + + + Change Account Password + + + + + Enter Current Password + + + + + Enter New Password + + + + + Confirm New Password + + + + + Confirm + + + + + Cancel + Prekliči + + + + Current Password Incorrect + + + + + PhotoBoothDialog + + + Photobooth + Foto stojnica + + + + PhotoboothWidget + + + Form + Obrazec + + + + Photobooth display + + + + + Choose File + Izberi datoteko + + + + Image Files (*.jpg *.jpeg *.png) + + + + + PrivateBridging + + + Choose File + Izberi datoteko + + + + Files (*) + Datoteke (*) + + + + QObject + + + No default mail client found + Ne najdem privzetega programa za e-pošto + + + + + Edit Device Name + + + + + Unlink Device From Account + + + + + Save new device name + + + + + Add as contact + + + + + RingButton + + + Select folder + + + + + SettingsWidget + + + Form + Obrazec + + + + Settings + Nastavitve + + + + Account + Račun + + + + + General + Splošno + + + + + Audio / Video + + + + + System + Sistem + + + + Enable desktop notifications + + + + + Keep minimized on close + Minimiziraj ob zaprtju + + + + Download folder + + + + + Save in + + + + + Always Recording + + + + + Updates + + + + + Check for updates automatically every + + + + + Interval between update checks in days selector + + + + + days + + + + + Check for updates now button + + + + + Check for updates now + Preveri posodobitve zdaj + + + + Password + Geslo + + + + + Enable + + + + + toggle enable notifications + + + + + Toggle keep minimized on close + + + + + Call Recordings + + + + + Toggle automatic updates + + + + + Jami Account + + + + + + Profile + Profil + + + + + Identity + Identiteta + + + + Id + ID + + + + Registered name + Prijavljeno ime + + + + Type here to register a username + + + + + Register + Prijavi se + + + + Change Password + + + + + Export Account + + + + + + Delete Account + + + + + Linked Devices + + + + + Link Another Device + + + + + Banned Contacts + Zavrnjeni stiki + + + + Format + + + + + Video device framerate selector + + + + + Preview unavailable + + + + + + Advanced Account Settings + + + + + SIP Account + SIP račun + + + + Username + Uporabnik + + + + Hostname + Strežnik + + + + Proxy + Proxy + + + + Audio + Avdio + + + + Microphone + + + + + Audio input device selector + + + + + Output Device + Izhodna naprava + + + + Choose the output device + + + + + Video + Video + + + + Device + Naprava + + + + Video device selector + + + + + A registered name should not have any spaces and must be at least three letters long + + + + + This name is already taken + + + + + + Enter an alias + + + + + Register this name + + + + + Remove Device + + + + + Enter this account's password to confirm the removal of this device + + + + + Are you sure you wish to remove this device? + + + + + Export Account Here + + + + + Select A Folder For Your Downloads + + + + + Select A Folder For Your Recordings + + + + + VideoOverlay + + + Call on Hold + Klic na čakanju + + + + Hold / Unhold + Čakanje / Nadaljevanje + + + + Chat + Pogovor + + + + Mute Mic + Izključi mikrofon + + + + Record call + + + + + Name label + Oznaka imena + + + + Time elapsed + Pretečeni čas + + + + 00:00 + 00:00 + + + + Hangup + Prekini + + + + Mute Video + Izključi video + + + + VideoView + + + Share entire screen + Deli celoten zaslon + + + + Share screen area + Deli območje zaslona + + + + Share file + Deli datoteko + + + \ No newline at end of file diff --git a/translations/ring_client_windows_sq_AL.ts b/translations/ring_client_windows_sq_AL.ts new file mode 100644 index 00000000..3a02cfd5 --- /dev/null +++ b/translations/ring_client_windows_sq_AL.ts @@ -0,0 +1,1605 @@ + + + AboutDialog + + + + About + Mbi + + + + about button + buton Mbi + + + + credits button + buton Kreditesh + + + + Credits + Kredite + + + + Free as in Freedom + I lirë si në Liri + + + + The Microsoft Windows client for Jami. +Jami is a secured and distributed communication software. + Klienti Jami për Microsoft Windows. +Jami është një software komunikimi të siguruar dhe të shpërndarë. + + + + version + version + + + + Created by: + Krijuar nga: + + + + Artwork by: + Përkujdesja grafike: + + + + Based on the SFLPhone project + Bazuar në projektin SFLPhone + + + + AccountItemDelegate + + + Add Account + Shtoni Llogari + + + + AdvancedSIPSettingsWidget + + + Form + Formular + + + + Call Settings + Rregullime për Thirrjet + + + + Auto Answer Calls + Vetëpërgjigjiu Thirrjeve + + + + Enable Custom Ringtone + Aktivizo Zile Vetjake + + + + Connectivity + Aftësi lidhjeje + + + + STUN Address + Adresë STUN + + + + Use STUN + Përdor STUN + + + + Use UPnP + Përdor UPnP + + + + Use TURN + Përdor TURN + + + + TURN Password + Fjalëkalim TURN + + + + TURN Username + Emër përdoruesi TURN + + + + TURN Address + Adresë TURN + + + + Media + Media + + + + Enable Video + Aktivizo Video + + + + Video Codecs + Kodekë Video + + + + Audio Codecs + Kodekë Audio + + + + Audio Files (*.wav *.ogg *.opus *.mp3 *aiff *wma) + Kartela Audio (*.wav *.ogg *.opus *.mp3 *aiff *wma) + + + + Add a custom ringtone + Shtoni një zile vetjake + + + + AdvancedSettingsWidget + + + Form + Formular + + + + Call Settings + Rregullime për Thirrjet + + + + Allow Calls From Untrusted Peers + Lejo Thirrje Prej Ortakësh Jo të Besuar + + + + Auto Answer Calls + Vetëpërgjigjiu Thirrjeve + + + + Enable Custom Ringtone + Aktivizo Zile Vetjake + + + + Add a custom ringtone + Shtoni një zile vetjake + + + + Name Server + Shërbyes Emrash + + + + Address + Adresë + + + + OpenDHT Configuration + Formësim OpenDHT-je + + + + Enable Proxy + Aktivizo Ndërmjetës + + + + Bootstrap + Bootstrap + + + + Security + Siguri + + + + Private Key Password + Fjalëkalim Kyçi Privat + + + + User Certificate + Dëshmi Përdoruesi + + + + Private Key + Kyç Privat + + + + CA Certificate + Dëshmi AD + + + + Connectivity + Aftësi lidhjeje + + + + Use STUN + Përdor STUN + + + + STUN Address + Adresë STUN + + + + Use UPnP + Përdor UPnP + + + + Use TURN + Përdor TURN + + + + TURN Password + Fjalëkalim TURN + + + + TURN Username + Emër përdoruesi TURN + + + + TURN Address + Adresë TURN + + + + Media + Media + + + + Enable Video + Aktivizo Video + + + + Audio Codecs + Kodekë Audio + + + + Video Codecs + Kodekë Video + + + + Audio Files (*.wav *.ogg *.opus *.mp3 *aiff *wma) + Kartela Audio (*.wav *.ogg *.opus *.mp3 *aiff *wma) + + + + AnimatedOverlay + + + Form + Formular + + + + BannedItemWidget + + + Form + Formular + + + + name + emër + + + + id + id + + + + CallWidget + + + Show conversations + Shfaq biseda + + + + Conversations + Biseda + + + + Search contact text input + Dhënie teksti kërkimi kontakti + + + + Jami is free software for universal communication which respects the freedoms and privacy of its users. + Jami është software i lirë për komunikim universal që respekton privatësinë e përdoruesve të tij. + + + + + This is your ID. +Copy and share it with your friends! + + +Kjo është ID-ja juaj. +Kopjojeni dhe jepuani shokëve! + + + + Show ring ID QR code + Shfaq kod QR ID-je Ring-u + + + + Share ring ID button + Buton Ndani ID Ringu Me të Tjerët + + + + Double-click to copy + Dyklikojeni që të kopjohet + + + + Error while generating QR Code + Gabim teksa prodhohej kodi QR + + + + + best name + Përzgjedhës shpejtësie kuadrosh për pajisje video + + + + best Id + + + + + Back to homepage button + Buton Mbrapsht te faqja hyrëse + + + + Add to contacts + Shtoje te kontaktet + + + + Show invites + Shfaq ftesa + + + + Invites + Ftesa + + + + + Find a new or existing contact + Gjeni një kontakt të ri ose ekzistues + + + + Wants to talk to you! + Dëshiron të bisedojë me ju! + + + + Answer incoming call button + Buton Përgjigjuni thirrjes ardhëse + + + + Ignore incoming call button + Buton Shpërfille thirrjen ardhëse + + + + Answer + Përgjigjuni + + + + Ignore + Shpërfille + + + + Cancel outgoing call + Anuloje dërgimin e thirrjes + + + + Cancel + Anuloje + + + + Start video call + Filloni thirrje video + + + + Start audio call + Filloni thirrje audio + + + + Clear conversation + Spastroje bisedën + + + + Remove contact + Hiqe kontaktin + + + + Block contact + Bllokojeni kontaktin + + + + Copy number + Kopjoje numrin + + + + Search your received invitations + Kërkoni te ftesat tuaja të marra + + + + Contact me on Jami + Lidhuni me mua në Jami + + + + My Id is : + ID-ja ime është: + + + + %1 + %1 is the contact username + %1 + + + + %1 + %1 is the contact unique identifier + %1 + + + + Call incoming from %1 + Thirrje ardhur nga %1 + + + + DeleteAccountDialog + + + Account deletion + Fshirje llogarie + + + + Do you really want to delete the following account? + Doni vërtet të fshihet llogaria vijuese? + + + + If this account hasn't been exported, or added to another device, it will be irrevocably lost. + Nëse kjo llogari s’është eksportuar, ose shtuar te një tjetër pajisje, do të humbë në mënyrë të pakthyeshme. + + + + Permanently delete account + Fshije llogarinë përgjithmonë + + + + Delete + Fshije + + + + Cancel account deletion + Anulo fshirje llogarie + + + + Cancel + Anuloje + + + + DeviceItemWidget + + + Form + Formular + + + + Device Id + ID pajisjeje + + + + this device + këtë pajisje + + + + InviteButtonsWidget + + + Accept + Pranoje + + + + Refuse + Hidhe tej + + + + Block + Bllokoje + + + + LinkDeviceDialog + + + Dialog + Dialog + + + + Enter your account password + Jepni fjalëkalimin e llogarisë tuaj + + + + Password + Fjalëkalim + + + + Ok + OK + + + + Cancel + Anuloje + + + + Exporting account + Po eksportohet llogari + + + + Your PIN is + PIN-i juaj është + + + + PIN + PIN + + + + This pin and the account password should be entered in your device within 10 minutes. + Ky PIN dhe fjalëkalimi i llogarisë duhen dhënë te pajisja juaj brenda 10 minutash + + + + Close + Mbylle + + + + Link Another Device + Lidhni Një Pajisje Tjetër + + + + Incorrect password + Fjalëkalim i pasaktë + + + + Something went wrong. +Please try again later. + Diç shkoi ters. +Ju lutemi, riprovoni më vonë. + + + + MainWindow + + + Settings + Rregullime + + + + Exit + Dalje + + + + About + Mbi + + + + Jami + Jami + + + + NameRegistrationDialog + + + Set Registered Name + Caktoni Emër të Regjistruar + + + + Enter your account password + Jepni fjalëkalimin e llogarisë tuaj + + + + Password text input + Dhënie teksti fjalëkalimi + + + + Password text entry + Dhënie teksti fjalëkalimi + + + + Password + Fjalëkalim + + + + Register + Regjistrohuni + + + + Cancel + Anuloje + + + + Registering Name + Po Regjistrohet Emër + + + + Something went wrong + Diç shkoi ters + + + + Close + Mbylle + + + + Incorrect password + Fjalëkalim i pasaktë + + + + Network error + Gabim rrjeti + + + + NewWizardWidget + + + Form + Formular + + + + Welcome Label + Etiketë Mirëseardhjeje + + + + Welcome to + Mirë se vini te + + + + Welcome Logo + Logo Mirëseardhjeje + + + + Create Jami account button + Buton Krijoni llogari Jami + + + + Push button for Jami account creation start trigger + Buton për të shkaktuar fillimin e krijimit të llogarisë Jami + + + + Create a Jami account + Krijoni një llogari Jami + + + + Link device button + Buton Lidhni pajisje + + + + Push button for device linkage start trigger + Buton për të shkaktuar fillimin e lidhjes së një llogarie + + + + Link this device to an account + Lidheni këtë pajisje me një llogari + + + + Create Jami SIP account button + Krijoni buton llogarie SIP Jami + + + + Push button for Jami SIP account creation start trigger + Buton për të shkaktuar fillimin e krijimit të llogarisë SIP Jami + + + + Create a SIP account + Krijoni llogari SIP + + + + Link this device to an existing account + Lidheni këtë pajisje me një llogari ekzistuese + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Ubuntu'; font-size:14px; color:#555555;">To link this device to another account, you first </span><span style=" font-family:'Ubuntu'; font-size:14px; font-weight:600; color:#555555;">need to obtain a PIN</span><span style=" font-family:'Ubuntu'; font-size:14px; color:#555555;"> code. To generate the PIN code:</span></p> +<ol style="margin-top: 0px; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; -qt-list-indent: 1;"><li style=" font-family:'Ubuntu'; font-size:14px; color:#555555;" style=" margin-top:12px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:14px;">Go to the </span><span style=" font-size:14px; font-weight:600;">Account management setting</span><span style=" font-size:14px;"> of a previous device</span></li> +<li style=" font-family:'Ubuntu'; font-size:14px; color:#555555;" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:14px;">Choose the </span><span style=" font-size:14px; font-weight:600;">Jami account</span><span style=" font-size:14px;"> you want to use</span></li> +<li style=" font-family:'Ubuntu'; font-size:14px; color:#555555;" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:14px;">Go to the </span><span style=" font-size:14px; font-weight:600;">Devices</span><span style=" font-size:14px;"> tab</span></li> +<li style=" font-family:'Ubuntu'; font-size:14px; color:#555555;" style=" margin-top:0px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:14px;">Select </span><span style=" font-size:14px; font-weight:600;">Add a device</span></li></ol> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Ubuntu'; font-size:14px; color:#555555;">You will get the necessary PIN to complete this form. The PIN is only valid for </span><span style=" font-family:'Ubuntu'; font-size:14px; font-weight:600; color:#555555;">10 minutes</span><span style=" font-family:'Ubuntu'; font-size:10px; color:#555555;">.</span></p></body></html> + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Ubuntu'; font-size:14px; color:#555555;">Që të lidhni këtë pajisje me një tjetër llogari, së pari </span><span style=" font-family:'Ubuntu'; font-size:14px; font-weight:600; color:#555555;">lypset të merrni një kod PIN</span><span style=" font-family:'Ubuntu'; font-size:14px; color:#555555;">. Që të prodhoni kodin PIN:</span></p> +<ol style="margin-top: 0px; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; -qt-list-indent: 1;"><li style=" font-family:'Ubuntu'; font-size:14px; color:#555555;" style=" margin-top:12px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:14px;">Shkoni te </span><span style=" font-size:14px; font-weight:600;">rregullimi Administrim llogarie</span><span style=" font-size:14px;"> i një pajisje të mëparshme</span></li> +<li style=" font-family:'Ubuntu'; font-size:14px; color:#555555;" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:14px;">Zgjidhni </span><span style=" font-size:14px; font-weight:600;">llogarinë Jami</span><span style=" font-size:14px;"> që doni të përdoret</span></li> +<li style=" font-family:'Ubuntu'; font-size:14px; color:#555555;" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:14px;">Shkoni te skeda </span><span style=" font-size:14px; font-weight:600;">Pajisje</span><span style=" font-size:14px;"></span></li> +<li style=" font-family:'Ubuntu'; font-size:14px; color:#555555;" style=" margin-top:0px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:14px;">përzgjidhni </span><span style=" font-size:14px; font-weight:600;">Shtoni një pajisje</span></li></ol> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Ubuntu'; font-size:14px; color:#555555;">Do të merrni PIN-in e nevojshëm për plotësimin e këtij formulari. PIN-i është i vlefshëm vetëm për </span><span style=" font-family:'Ubuntu'; font-size:14px; font-weight:600; color:#555555;">10 minuta</span><span style=" font-family:'Ubuntu'; font-size:10px; color:#555555;">.</span></p></body></html> + + + + Enter your pin: + Jepni PIN-in tuaj: + + + + Or import a file: + Ose importoni një kartelë: + + + + Link from exported account archive file + Lidheni prej kartele arkivi të eksportuar llogarie + + + + + + (None) + (Asnjë) + + + + Password: + Fjalëkalim: + + + + + Profile + Profil + + + + + Profile name + Emër profili + + + + Account + Llogari + + + + Register your username. +This will reserve the username so that only you can use it. +Your friends will be able to call you with your usename +instead of using your ID. + Regjistroni emrin tuaj të përdoruesit. +Kjo do të bëjë rezervimin e emrit të përdoruesit, që kështu vetëm ju mund ta përdorni. +Shokët tuaj do të jenë në gjendje t’ju bëjnë thirrje me emrin tuaj të përdoruesit +në vend se të përdorin ID-në tuaj. + + + + Public username checkbox + Kutizë emri publik përdoruesi + + + + Checkbox selecting if the user wants a public username + Kutizë përzgjedhjeje nëse përdoruesi dëshiron një emër publik përdoruesi + + + + Register public username + Regjistroni emër publik përdoruesi + + + + Public username edit + Përpunim emri publik përdoruesi + + + + Choose your username + Zgjidhni mrin tuaj të përdoruesit + + + + Password text input + Dhënie teksti fjalëkalimi + + + + Password text entry + Dhënie teksti fjalëkalimi + + + + + Password + Fjalëkalim + + + + + Password confirmation text input + Dhënie teksti ripohimi fjalëkalimi + + + + Confirm password + Ripohoni fjalëkalimin + + + + SIP Account + Llogari SIP + + + + SIP Server edit + Përpunim Shërbyesi SIP + + + + Server + Shërbyes + + + + SIP proxy input + Dhënie ndërmjetësi SIP + + + + SIP proxy text entry + Zë teksti ndërmjetësi SIP + + + + Proxy + Ndërmjetës + + + + SIP username input + Dhënie emri përdoruesi SIP + + + + SIP Password text entry + Zë teksti Fjalëkalimi SIP + + + + Username + Emër përdoruesi + + + + + SIP Password text input + Dhënie teksti fjalëkalimi SIP + + + + Generating your Jami account… + Po prodhohet llogaria juaj Jami… + + + + Previous page button + Buton Faqja e mëparshme + + + + push button to access previous page of wizard + buton për të kaluar te faqja e mëparshme e ndihmësit + + + + Previous + I mëparshmi + + + + Cancel account create/link + Anuloni krijim/lidhje llogarie + + + + push button to cancel account creation or linking + shtypni butoni që të anulohet krijimi ose lidhja e llogarisë + + + + Back + Mbrapsht + + + + Next page Button + Buton Faqja pasuese + + + + Push button to access next page of wizard + buton për të kaluar te faqja pasuese e ndihmësit + + + + Next + Pasuesi + + + + Open File + Hapni Kartelë + + + + Jami archive files (*.gz); All files (*) + Kartela arkivi Jami (*.gz); Krejt kartelat (*) + + + + Your account needs to be migrated. Enter your password. + Lypset të migrohet llogaria juaj. Jepni fjalëkalimin tuaj. + + + + Migrating your Jami account... + Po migrohet llogaria juaj Jami… + + + + Importing account archive... + Po importohet arkiv llogarie… + + + + Generating your Jami account... + Po prodhohet llogaria juaj Jami… + + + + Generating your SIP account... + Po prodhohet llogaria juaj SIP… + + + + Error creating account + Gabim në krijimin e llogarisë + + + + PasswordDialog + + + Change Account Password + Ndryshoni Fjalëkalim Llogarie + + + + Enter Current Password + Jepni Fjalëkalimin e Tanishëm + + + + Enter New Password + Jepni Fjalëkalimin e Ri + + + + Confirm New Password + Ripohoni Fjalëkalim të Ri + + + + Confirm + Ripohoje + + + + Cancel + Anuloje + + + + Current Password Incorrect + Fjalëkalim i Tanishëm i Pasaktë + + + + PhotoBoothDialog + + + Photobooth + Kioskë fotosh + + + + PhotoboothWidget + + + Form + Formular + + + + Photobooth display + Shfaqje kioske fotosh + + + + Choose File + Zgjidhni Kartelë + + + + Image Files (*.jpg *.jpeg *.png) + Kartela Figurash (*.jpg *.jpeg *.png) + + + + PrivateBridging + + + Choose File + Zgjidhni Kartelë + + + + Files (*) + Kartela (*) + + + + QObject + + + No default mail client found + S’u gjet klient parazgjedhje poste + + + + + Edit Device Name + Përpunoni Emër Pajisjeje + + + + Unlink Device From Account + Hiqini Lidhjen Prej Llogarie Kësaj Pajisjeje + + + + Save new device name + Ruani emrin e pajisjes së re + + + + Add as contact + Shtojeni si kontakt + + + + RingButton + + + Select folder + Përzgjidhni dosje + + + + SettingsWidget + + + Form + Formular + + + + Settings + Rregullime + + + + Account + Llogari + + + + + General + Të përgjithshme + + + + + Audio / Video + Audio / Video + + + + System + Sistem + + + + Enable desktop notifications + Aktivizoni njoftime nga desktopi + + + + Keep minimized on close + Mbaje të minimizuar kur dilet + + + + Download folder + Dosje Shkarkimi + + + + Save in + Ruaje te + + + + Always Recording + Përherë Në Regjistrim + + + + Updates + Përditësime + + + + Check for updates automatically every + Kontrollo vetvetiu për përditësime çdo + + + + Interval between update checks in days selector + Përzgjedhës intervali mes kontrollesh për përditësime, në ditë + + + + days + ditë + + + + Check for updates now button + Buton Kontrollo tani për përditësime + + + + Check for updates now + Kontrollo tani për përditësime + + + + Password + Fjalëkalim + + + + + Enable + Aktivizoje + + + + toggle enable notifications + aktivizo/çaktivizo njoftime + + + + Toggle keep minimized on close + Këmbe zgjedhjen për “Mbaje të minimizuar kur dilet” + + + + Call Recordings + Incizim Thirrjesh + + + + Toggle automatic updates + Aktivizo/çaktivizo përditësime të automatizuara + + + + Jami Account + Llogari Jami + + + + + Profile + Profil + + + + + Identity + Identitet + + + + Id + ID + + + + Registered name + Emër i regjistruar + + + + Type here to register a username + Shtypni këtu që të regjistroni një emër përdoruesi + + + + Register + Regjistrohuni + + + + Change Password + Ndryshoni Fjalëkalimin + + + + Export Account + Eksportoje Llogarinë + + + + + Delete Account + Fshije Llogarinë + + + + Linked Devices + Pajisje të Lidhura + + + + Link Another Device + Lidhni Një Pajisje Tjetër + + + + Banned Contacts + Kontakte të Dëbuar + + + + Format + Format + + + + Video device framerate selector + Përzgjedhës shpejtësie kuadrosh pajisjeje video + + + + Preview unavailable + S’ka paraparje + + + + + Advanced Account Settings + Rregullime të Mëtejshme Llogarie + + + + SIP Account + Llogari SIP + + + + Username + Emër përdoruesi + + + + Hostname + Strehëemër + + + + Proxy + Ndërmjetës + + + + Audio + Audio + + + + Microphone + Mikrofon + + + + Audio input device selector + Përzgjedhës pajisje audio në hyrje + + + + Output Device + Pajisje Në Dalje + + + + Choose the output device + Zgjidhni pajisje output-i + + + + Video + Video + + + + Device + Pajisje + + + + Video device selector + Përzgjedhës pajisje video + + + + A registered name should not have any spaces and must be at least three letters long + Emri i regjistruar s’duhet të përmbajë hapësira dhe duhet të jetë të paktën tre shkronja i gjatë + + + + This name is already taken + Ky emër është zënë tashmë + + + + + Enter an alias + Jepni një alias + + + + Register this name + Regjistro këtë emër + + + + Remove Device + Hiqe Pajisjen + + + + Enter this account's password to confirm the removal of this device + Që të ripohoni heqjen e kësaj pajisje, jepni fjalëkalimin e kësaj llogarie + + + + Are you sure you wish to remove this device? + Jeni i sigurt se doni të hiqet kjo pajisje? + + + + Export Account Here + Eksportoje Llogarinë Këtu + + + + Select A Folder For Your Downloads + Përzgjidhni Një Dosje Për Shkarkimet Tuaja + + + + Select A Folder For Your Recordings + Përzgjidhni Një Dosje Për Regjistrimet Tuaja + + + + VideoOverlay + + + Call on Hold + Thirrje Pezull + + + + Hold / Unhold + Mbaje Pezull/Rimerre + + + + Chat + Fjalosje + + + + Mute Mic + Heshtoje Mikrofonin + + + + Record call + Incizo thirrjen + + + + Name label + Etiketë emri + + + + Time elapsed + Kohë e rrjedhur + + + + 00:00 + 00:00 + + + + Hangup + Mbylle + + + + Mute Video + Hiqi Zërin Videos + + + + VideoView + + + Share entire screen + Nda krejt ekranin + + + + Share screen area + Ndani me të tjerët zonën e ekranit + + + + Share file + Ndani kartelë me të tjerë + + + \ No newline at end of file diff --git a/translations/ring_client_windows_sr@latin.ts b/translations/ring_client_windows_sr@latin.ts new file mode 100644 index 00000000..bd133c6f --- /dev/null +++ b/translations/ring_client_windows_sr@latin.ts @@ -0,0 +1,1589 @@ + + + AboutDialog + + + + About + + + + + about button + + + + + credits button + + + + + Credits + Zasluge + + + + Free as in Freedom + + + + + The Microsoft Windows client for Jami. +Jami is a secured and distributed communication software. + + + + + version + + + + + Created by: + + + + + Artwork by: + + + + + Based on the SFLPhone project + + + + + AccountItemDelegate + + + Add Account + + + + + AdvancedSIPSettingsWidget + + + Form + + + + + Call Settings + + + + + Auto Answer Calls + + + + + Enable Custom Ringtone + + + + + Connectivity + + + + + STUN Address + + + + + Use STUN + + + + + Use UPnP + + + + + Use TURN + + + + + TURN Password + + + + + TURN Username + + + + + TURN Address + + + + + Media + + + + + Enable Video + + + + + Video Codecs + + + + + Audio Codecs + + + + + Audio Files (*.wav *.ogg *.opus *.mp3 *aiff *wma) + + + + + Add a custom ringtone + + + + + AdvancedSettingsWidget + + + Form + + + + + Call Settings + + + + + Allow Calls From Untrusted Peers + + + + + Auto Answer Calls + + + + + Enable Custom Ringtone + + + + + Add a custom ringtone + + + + + Name Server + + + + + Address + + + + + OpenDHT Configuration + + + + + Enable Proxy + + + + + Bootstrap + + + + + Security + + + + + Private Key Password + + + + + User Certificate + + + + + Private Key + + + + + CA Certificate + + + + + Connectivity + + + + + Use STUN + + + + + STUN Address + + + + + Use UPnP + + + + + Use TURN + + + + + TURN Password + + + + + TURN Username + + + + + TURN Address + + + + + Media + + + + + Enable Video + + + + + Audio Codecs + + + + + Video Codecs + + + + + Audio Files (*.wav *.ogg *.opus *.mp3 *aiff *wma) + + + + + AnimatedOverlay + + + Form + + + + + BannedItemWidget + + + Form + + + + + name + + + + + id + + + + + CallWidget + + + Show conversations + + + + + Conversations + + + + + Search contact text input + + + + + Jami is free software for universal communication which respects the freedoms and privacy of its users. + Jami je besplatan i slobodan softver za univerzalnu komunikaciju, koji poštuje slobode i privatnost svojih korisnika + + + + + This is your ID. +Copy and share it with your friends! + + + + + + Show ring ID QR code + + + + + Share ring ID button + + + + + Double-click to copy + + + + + Error while generating QR Code + + + + + + best name + + + + + best Id + + + + + Back to homepage button + + + + + Add to contacts + + + + + Show invites + + + + + Invites + + + + + + Find a new or existing contact + + + + + Wants to talk to you! + + + + + Answer incoming call button + + + + + Ignore incoming call button + + + + + Answer + + + + + Ignore + + + + + Cancel outgoing call + + + + + Cancel + Otkaži + + + + Start video call + + + + + Start audio call + + + + + Clear conversation + + + + + Remove contact + + + + + Block contact + + + + + Copy number + + + + + Search your received invitations + + + + + Contact me on Jami + + + + + My Id is : + + + + + %1 + %1 is the contact username + + + + + %1 + %1 is the contact unique identifier + + + + + Call incoming from %1 + + + + + DeleteAccountDialog + + + Account deletion + + + + + Do you really want to delete the following account? + + + + + If this account hasn't been exported, or added to another device, it will be irrevocably lost. + + + + + Permanently delete account + + + + + Delete + + + + + Cancel account deletion + + + + + Cancel + Otkaži + + + + DeviceItemWidget + + + Form + + + + + Device Id + + + + + this device + + + + + InviteButtonsWidget + + + Accept + + + + + Refuse + + + + + Block + + + + + LinkDeviceDialog + + + Dialog + + + + + Enter your account password + + + + + Password + + + + + Ok + + + + + Cancel + Otkaži + + + + Exporting account + + + + + Your PIN is + + + + + PIN + + + + + This pin and the account password should be entered in your device within 10 minutes. + + + + + Close + + + + + Link Another Device + + + + + Incorrect password + + + + + Something went wrong. +Please try again later. + + + + + MainWindow + + + Settings + + + + + Exit + + + + + About + + + + + Jami + + + + + NameRegistrationDialog + + + Set Registered Name + + + + + Enter your account password + + + + + Password text input + + + + + Password text entry + + + + + Password + + + + + Register + + + + + Cancel + Otkaži + + + + Registering Name + + + + + Something went wrong + + + + + Close + + + + + Incorrect password + + + + + Network error + + + + + NewWizardWidget + + + Form + + + + + Welcome Label + + + + + Welcome to + + + + + Welcome Logo + + + + + Create Jami account button + + + + + Push button for Jami account creation start trigger + + + + + Create a Jami account + Napravi Jami profil + + + + Link device button + + + + + Push button for device linkage start trigger + + + + + Link this device to an account + Poveži uređaj sa profilom + + + + Create Jami SIP account button + + + + + Push button for Jami SIP account creation start trigger + + + + + Create a SIP account + + + + + Link this device to an existing account + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Ubuntu'; font-size:14px; color:#555555;">To link this device to another account, you first </span><span style=" font-family:'Ubuntu'; font-size:14px; font-weight:600; color:#555555;">need to obtain a PIN</span><span style=" font-family:'Ubuntu'; font-size:14px; color:#555555;"> code. To generate the PIN code:</span></p> +<ol style="margin-top: 0px; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; -qt-list-indent: 1;"><li style=" font-family:'Ubuntu'; font-size:14px; color:#555555;" style=" margin-top:12px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:14px;">Go to the </span><span style=" font-size:14px; font-weight:600;">Account management setting</span><span style=" font-size:14px;"> of a previous device</span></li> +<li style=" font-family:'Ubuntu'; font-size:14px; color:#555555;" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:14px;">Choose the </span><span style=" font-size:14px; font-weight:600;">Jami account</span><span style=" font-size:14px;"> you want to use</span></li> +<li style=" font-family:'Ubuntu'; font-size:14px; color:#555555;" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:14px;">Go to the </span><span style=" font-size:14px; font-weight:600;">Devices</span><span style=" font-size:14px;"> tab</span></li> +<li style=" font-family:'Ubuntu'; font-size:14px; color:#555555;" style=" margin-top:0px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:14px;">Select </span><span style=" font-size:14px; font-weight:600;">Add a device</span></li></ol> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Ubuntu'; font-size:14px; color:#555555;">You will get the necessary PIN to complete this form. The PIN is only valid for </span><span style=" font-family:'Ubuntu'; font-size:14px; font-weight:600; color:#555555;">10 minutes</span><span style=" font-family:'Ubuntu'; font-size:10px; color:#555555;">.</span></p></body></html> + + + + + Enter your pin: + + + + + Or import a file: + + + + + Link from exported account archive file + + + + + + + (None) + + + + + Password: + + + + + + Profile + + + + + + Profile name + + + + + Account + + + + + Register your username. +This will reserve the username so that only you can use it. +Your friends will be able to call you with your usename +instead of using your ID. + + + + + Public username checkbox + + + + + Checkbox selecting if the user wants a public username + + + + + Register public username + + + + + Public username edit + + + + + Choose your username + + + + + Password text input + + + + + Password text entry + + + + + + Password + + + + + + Password confirmation text input + + + + + Confirm password + + + + + SIP Account + + + + + SIP Server edit + + + + + Server + + + + + SIP proxy input + + + + + SIP proxy text entry + + + + + Proxy + + + + + SIP username input + + + + + SIP Password text entry + + + + + Username + + + + + + SIP Password text input + + + + + Generating your Jami account… + + + + + Previous page button + + + + + push button to access previous page of wizard + + + + + Previous + + + + + Cancel account create/link + + + + + push button to cancel account creation or linking + + + + + Back + Nazad + + + + Next page Button + + + + + Push button to access next page of wizard + + + + + Next + + + + + Open File + + + + + Jami archive files (*.gz); All files (*) + + + + + Your account needs to be migrated. Enter your password. + + + + + Migrating your Jami account... + + + + + Importing account archive... + + + + + Generating your Jami account... + + + + + Generating your SIP account... + + + + + Error creating account + + + + + PasswordDialog + + + Change Account Password + + + + + Enter Current Password + + + + + Enter New Password + + + + + Confirm New Password + + + + + Confirm + + + + + Cancel + Otkaži + + + + Current Password Incorrect + + + + + PhotoBoothDialog + + + Photobooth + + + + + PhotoboothWidget + + + Form + + + + + Photobooth display + + + + + Choose File + + + + + Image Files (*.jpg *.jpeg *.png) + + + + + PrivateBridging + + + Choose File + + + + + Files (*) + + + + + QObject + + + No default mail client found + + + + + + Edit Device Name + + + + + Unlink Device From Account + + + + + Save new device name + + + + + Add as contact + + + + + RingButton + + + Select folder + + + + + SettingsWidget + + + Form + + + + + Settings + + + + + Account + + + + + + General + + + + + + Audio / Video + + + + + System + + + + + Enable desktop notifications + + + + + Keep minimized on close + + + + + Download folder + + + + + Save in + + + + + Always Recording + + + + + Updates + + + + + Check for updates automatically every + + + + + Interval between update checks in days selector + + + + + days + + + + + Check for updates now button + + + + + Check for updates now + + + + + Password + + + + + + Enable + + + + + toggle enable notifications + + + + + Toggle keep minimized on close + + + + + Call Recordings + + + + + Toggle automatic updates + + + + + Jami Account + + + + + + Profile + + + + + + Identity + + + + + Id + + + + + Registered name + + + + + Type here to register a username + + + + + Register + + + + + Change Password + + + + + Export Account + + + + + + Delete Account + + + + + Linked Devices + + + + + Link Another Device + + + + + Banned Contacts + + + + + Format + + + + + Video device framerate selector + + + + + Preview unavailable + + + + + + Advanced Account Settings + + + + + SIP Account + + + + + Username + + + + + Hostname + + + + + Proxy + + + + + Audio + + + + + Microphone + + + + + Audio input device selector + + + + + Output Device + + + + + Choose the output device + + + + + Video + + + + + Device + + + + + Video device selector + + + + + A registered name should not have any spaces and must be at least three letters long + + + + + This name is already taken + + + + + + Enter an alias + + + + + Register this name + + + + + Remove Device + + + + + Enter this account's password to confirm the removal of this device + + + + + Are you sure you wish to remove this device? + + + + + Export Account Here + + + + + Select A Folder For Your Downloads + + + + + Select A Folder For Your Recordings + + + + + VideoOverlay + + + Call on Hold + + + + + Hold / Unhold + + + + + Chat + + + + + Mute Mic + + + + + Record call + + + + + Name label + + + + + Time elapsed + + + + + 00:00 + + + + + Hangup + + + + + Mute Video + + + + + VideoView + + + Share entire screen + + + + + Share screen area + + + + + Share file + + + + \ No newline at end of file diff --git a/translations/ring_client_windows_sv.ts b/translations/ring_client_windows_sv.ts new file mode 100644 index 00000000..ce5f9265 --- /dev/null +++ b/translations/ring_client_windows_sv.ts @@ -0,0 +1,1589 @@ + + + AboutDialog + + + + About + Om + + + + about button + + + + + credits button + + + + + Credits + Tack till + + + + Free as in Freedom + + + + + The Microsoft Windows client for Jami. +Jami is a secured and distributed communication software. + + + + + version + version + + + + Created by: + Skapad av: + + + + Artwork by: + Bildkonst av: + + + + Based on the SFLPhone project + Baserad på SFLPhone-projektet + + + + AccountItemDelegate + + + Add Account + + + + + AdvancedSIPSettingsWidget + + + Form + Formulär + + + + Call Settings + + + + + Auto Answer Calls + + + + + Enable Custom Ringtone + + + + + Connectivity + Anslutningsbarhet + + + + STUN Address + + + + + Use STUN + Använd STUN + + + + Use UPnP + + + + + Use TURN + Använd TURN + + + + TURN Password + + + + + TURN Username + + + + + TURN Address + + + + + Media + Media + + + + Enable Video + Aktivera video + + + + Video Codecs + Videokodekar + + + + Audio Codecs + Ljudkodekar + + + + Audio Files (*.wav *.ogg *.opus *.mp3 *aiff *wma) + + + + + Add a custom ringtone + + + + + AdvancedSettingsWidget + + + Form + Formulär + + + + Call Settings + + + + + Allow Calls From Untrusted Peers + + + + + Auto Answer Calls + + + + + Enable Custom Ringtone + + + + + Add a custom ringtone + + + + + Name Server + + + + + Address + Adress + + + + OpenDHT Configuration + + + + + Enable Proxy + Aktivera proxy + + + + Bootstrap + Bootstrap + + + + Security + Säkerhet + + + + Private Key Password + Privat nyckellösenord + + + + User Certificate + Användarcertifikat + + + + Private Key + + + + + CA Certificate + + + + + Connectivity + Anslutningsbarhet + + + + Use STUN + Använd STUN + + + + STUN Address + + + + + Use UPnP + + + + + Use TURN + Använd TURN + + + + TURN Password + + + + + TURN Username + + + + + TURN Address + + + + + Media + Media + + + + Enable Video + Aktivera video + + + + Audio Codecs + Ljudkodekar + + + + Video Codecs + Videokodekar + + + + Audio Files (*.wav *.ogg *.opus *.mp3 *aiff *wma) + + + + + AnimatedOverlay + + + Form + Formulär + + + + BannedItemWidget + + + Form + Formulär + + + + name + + + + + id + + + + + CallWidget + + + Show conversations + + + + + Conversations + Konversationer + + + + Search contact text input + + + + + Jami is free software for universal communication which respects the freedoms and privacy of its users. + Jami är fri mjukvara för universell kommunikation, med respekt för användarens frihet och integritet. + + + + + This is your ID. +Copy and share it with your friends! + + + + + + Show ring ID QR code + + + + + Share ring ID button + + + + + Double-click to copy + Dubbelklicka för att kopiera + + + + Error while generating QR Code + Ett fel inträffade vid generering av QR-kod + + + + + best name + + + + + best Id + + + + + Back to homepage button + + + + + Add to contacts + Lägg till i kontakter + + + + Show invites + + + + + Invites + + + + + + Find a new or existing contact + + + + + Wants to talk to you! + Vill prata med dig! + + + + Answer incoming call button + + + + + Ignore incoming call button + + + + + Answer + Svara + + + + Ignore + Ignorera + + + + Cancel outgoing call + + + + + Cancel + Avbryt + + + + Start video call + + + + + Start audio call + + + + + Clear conversation + Rensa konversation + + + + Remove contact + Ta bort kontakt + + + + Block contact + Blockera kontakt + + + + Copy number + Kopiera nummer + + + + Search your received invitations + + + + + Contact me on Jami + + + + + My Id is : + + + + + %1 + %1 is the contact username + %1 + + + + %1 + %1 is the contact unique identifier + %1 + + + + Call incoming from %1 + Inkommande samtal från %1 + + + + DeleteAccountDialog + + + Account deletion + + + + + Do you really want to delete the following account? + + + + + If this account hasn't been exported, or added to another device, it will be irrevocably lost. + + + + + Permanently delete account + + + + + Delete + Ta bort + + + + Cancel account deletion + + + + + Cancel + Avbryt + + + + DeviceItemWidget + + + Form + Formulär + + + + Device Id + + + + + this device + denna enhet + + + + InviteButtonsWidget + + + Accept + Acceptera + + + + Refuse + Neka + + + + Block + Blockera + + + + LinkDeviceDialog + + + Dialog + Dialog + + + + Enter your account password + + + + + Password + Lösenord + + + + Ok + OK + + + + Cancel + Avbryt + + + + Exporting account + Exporterar konto + + + + Your PIN is + + + + + PIN + PIN-kod + + + + This pin and the account password should be entered in your device within 10 minutes. + + + + + Close + Stäng + + + + Link Another Device + + + + + Incorrect password + Felaktigt lösenord + + + + Something went wrong. +Please try again later. + + + + + MainWindow + + + Settings + Inställningar + + + + Exit + Avsluta + + + + About + Om + + + + Jami + Jami + + + + NameRegistrationDialog + + + Set Registered Name + + + + + Enter your account password + + + + + Password text input + + + + + Password text entry + + + + + Password + Lösenord + + + + Register + Registrera + + + + Cancel + Avbryt + + + + Registering Name + + + + + Something went wrong + + + + + Close + Stäng + + + + Incorrect password + Felaktigt lösenord + + + + Network error + Nätverksfel + + + + NewWizardWidget + + + Form + Formulär + + + + Welcome Label + + + + + Welcome to + Välkommen till + + + + Welcome Logo + + + + + Create Jami account button + + + + + Push button for Jami account creation start trigger + + + + + Create a Jami account + Skapa ett Jami-konto + + + + Link device button + + + + + Push button for device linkage start trigger + + + + + Link this device to an account + Koppla denna enhet till ett konto + + + + Create Jami SIP account button + + + + + Push button for Jami SIP account creation start trigger + + + + + Create a SIP account + + + + + Link this device to an existing account + Koppla den här enheten till ett befintligt konto + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Ubuntu'; font-size:14px; color:#555555;">To link this device to another account, you first </span><span style=" font-family:'Ubuntu'; font-size:14px; font-weight:600; color:#555555;">need to obtain a PIN</span><span style=" font-family:'Ubuntu'; font-size:14px; color:#555555;"> code. To generate the PIN code:</span></p> +<ol style="margin-top: 0px; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; -qt-list-indent: 1;"><li style=" font-family:'Ubuntu'; font-size:14px; color:#555555;" style=" margin-top:12px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:14px;">Go to the </span><span style=" font-size:14px; font-weight:600;">Account management setting</span><span style=" font-size:14px;"> of a previous device</span></li> +<li style=" font-family:'Ubuntu'; font-size:14px; color:#555555;" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:14px;">Choose the </span><span style=" font-size:14px; font-weight:600;">Jami account</span><span style=" font-size:14px;"> you want to use</span></li> +<li style=" font-family:'Ubuntu'; font-size:14px; color:#555555;" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:14px;">Go to the </span><span style=" font-size:14px; font-weight:600;">Devices</span><span style=" font-size:14px;"> tab</span></li> +<li style=" font-family:'Ubuntu'; font-size:14px; color:#555555;" style=" margin-top:0px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:14px;">Select </span><span style=" font-size:14px; font-weight:600;">Add a device</span></li></ol> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Ubuntu'; font-size:14px; color:#555555;">You will get the necessary PIN to complete this form. The PIN is only valid for </span><span style=" font-family:'Ubuntu'; font-size:14px; font-weight:600; color:#555555;">10 minutes</span><span style=" font-family:'Ubuntu'; font-size:10px; color:#555555;">.</span></p></body></html> + + + + + Enter your pin: + Ange din PIN-kod: + + + + Or import a file: + Eller importera en fil: + + + + Link from exported account archive file + + + + + + + (None) + (Ingen) + + + + Password: + Lösenord: + + + + + Profile + Profil + + + + + Profile name + + + + + Account + Konto + + + + Register your username. +This will reserve the username so that only you can use it. +Your friends will be able to call you with your usename +instead of using your ID. + + + + + Public username checkbox + + + + + Checkbox selecting if the user wants a public username + + + + + Register public username + Registrera offentligt användarnamn + + + + Public username edit + + + + + Choose your username + Välj användarnamn + + + + Password text input + + + + + Password text entry + + + + + + Password + Lösenord + + + + + Password confirmation text input + + + + + Confirm password + Bekräfta lösenord + + + + SIP Account + SIP-konto + + + + SIP Server edit + + + + + Server + + + + + SIP proxy input + + + + + SIP proxy text entry + + + + + Proxy + Proxy + + + + SIP username input + + + + + SIP Password text entry + + + + + Username + Användarnamn + + + + + SIP Password text input + + + + + Generating your Jami account… + Genererar ditt Jami-konto... + + + + Previous page button + + + + + push button to access previous page of wizard + + + + + Previous + Föregående + + + + Cancel account create/link + + + + + push button to cancel account creation or linking + + + + + Back + Tillbaka + + + + Next page Button + + + + + Push button to access next page of wizard + + + + + Next + Nästa + + + + Open File + Öppna fil + + + + Jami archive files (*.gz); All files (*) + + + + + Your account needs to be migrated. Enter your password. + Ditt konto måste migreras. Ange ditt lösenord. + + + + Migrating your Jami account... + + + + + Importing account archive... + + + + + Generating your Jami account... + + + + + Generating your SIP account... + + + + + Error creating account + Fel vid kontoskapande + + + + PasswordDialog + + + Change Account Password + + + + + Enter Current Password + + + + + Enter New Password + + + + + Confirm New Password + + + + + Confirm + + + + + Cancel + Avbryt + + + + Current Password Incorrect + + + + + PhotoBoothDialog + + + Photobooth + Photobooth + + + + PhotoboothWidget + + + Form + Formulär + + + + Photobooth display + + + + + Choose File + Välj fil + + + + Image Files (*.jpg *.jpeg *.png) + + + + + PrivateBridging + + + Choose File + Välj fil + + + + Files (*) + Filer (*) + + + + QObject + + + No default mail client found + Ingen ordinarie e-postklient hittades + + + + + Edit Device Name + + + + + Unlink Device From Account + + + + + Save new device name + + + + + Add as contact + + + + + RingButton + + + Select folder + + + + + SettingsWidget + + + Form + Formulär + + + + Settings + Inställningar + + + + Account + Konto + + + + + General + Allmänt + + + + + Audio / Video + + + + + System + System + + + + Enable desktop notifications + + + + + Keep minimized on close + Minimera istället för att avsluta + + + + Download folder + Nerladdningsmapp + + + + Save in + Spara i + + + + Always Recording + + + + + Updates + + + + + Check for updates automatically every + + + + + Interval between update checks in days selector + + + + + days + + + + + Check for updates now button + + + + + Check for updates now + Sök efter uppdateringar nu + + + + Password + Lösenord + + + + + Enable + Aktivera + + + + toggle enable notifications + + + + + Toggle keep minimized on close + + + + + Call Recordings + + + + + Toggle automatic updates + + + + + Jami Account + + + + + + Profile + Profil + + + + + Identity + Identitet + + + + Id + ID + + + + Registered name + Registrerat namn + + + + Type here to register a username + + + + + Register + Registrera + + + + Change Password + + + + + Export Account + Exportera konto + + + + + Delete Account + Ta bort konto + + + + Linked Devices + + + + + Link Another Device + + + + + Banned Contacts + Bannlysta kontakter + + + + Format + + + + + Video device framerate selector + + + + + Preview unavailable + + + + + + Advanced Account Settings + + + + + SIP Account + SIP-konto + + + + Username + Användarnamn + + + + Hostname + Värdnamn + + + + Proxy + Proxy + + + + Audio + Ljud + + + + Microphone + + + + + Audio input device selector + + + + + Output Device + Utdataenhet + + + + Choose the output device + + + + + Video + Video + + + + Device + Enhet + + + + Video device selector + + + + + A registered name should not have any spaces and must be at least three letters long + + + + + This name is already taken + + + + + + Enter an alias + + + + + Register this name + + + + + Remove Device + + + + + Enter this account's password to confirm the removal of this device + + + + + Are you sure you wish to remove this device? + + + + + Export Account Here + + + + + Select A Folder For Your Downloads + + + + + Select A Folder For Your Recordings + + + + + VideoOverlay + + + Call on Hold + Parkerat samtal + + + + Hold / Unhold + Parkera / Återuppta + + + + Chat + Chatt + + + + Mute Mic + Stäng av mikrofon + + + + Record call + + + + + Name label + Namnetikett + + + + Time elapsed + Förfluten tid + + + + 00:00 + 00:00 + + + + Hangup + Lägg på + + + + Mute Video + Pausa video + + + + VideoView + + + Share entire screen + Dela hela skärmen + + + + Share screen area + Dela skärmområde + + + + Share file + Dela fil + + + \ No newline at end of file diff --git a/translations/ring_client_windows_ta.ts b/translations/ring_client_windows_ta.ts new file mode 100644 index 00000000..3eb3c948 --- /dev/null +++ b/translations/ring_client_windows_ta.ts @@ -0,0 +1,1589 @@ + + + AboutDialog + + + + About + + + + + about button + + + + + credits button + + + + + Credits + + + + + Free as in Freedom + + + + + The Microsoft Windows client for Jami. +Jami is a secured and distributed communication software. + + + + + version + + + + + Created by: + + + + + Artwork by: + + + + + Based on the SFLPhone project + + + + + AccountItemDelegate + + + Add Account + + + + + AdvancedSIPSettingsWidget + + + Form + + + + + Call Settings + + + + + Auto Answer Calls + + + + + Enable Custom Ringtone + + + + + Connectivity + + + + + STUN Address + + + + + Use STUN + + + + + Use UPnP + + + + + Use TURN + + + + + TURN Password + + + + + TURN Username + + + + + TURN Address + + + + + Media + + + + + Enable Video + + + + + Video Codecs + + + + + Audio Codecs + + + + + Audio Files (*.wav *.ogg *.opus *.mp3 *aiff *wma) + + + + + Add a custom ringtone + + + + + AdvancedSettingsWidget + + + Form + + + + + Call Settings + + + + + Allow Calls From Untrusted Peers + + + + + Auto Answer Calls + + + + + Enable Custom Ringtone + + + + + Add a custom ringtone + + + + + Name Server + + + + + Address + + + + + OpenDHT Configuration + + + + + Enable Proxy + + + + + Bootstrap + + + + + Security + + + + + Private Key Password + + + + + User Certificate + + + + + Private Key + + + + + CA Certificate + + + + + Connectivity + + + + + Use STUN + + + + + STUN Address + + + + + Use UPnP + + + + + Use TURN + + + + + TURN Password + + + + + TURN Username + + + + + TURN Address + + + + + Media + + + + + Enable Video + + + + + Audio Codecs + + + + + Video Codecs + + + + + Audio Files (*.wav *.ogg *.opus *.mp3 *aiff *wma) + + + + + AnimatedOverlay + + + Form + + + + + BannedItemWidget + + + Form + + + + + name + + + + + id + + + + + CallWidget + + + Show conversations + + + + + Conversations + + + + + Search contact text input + + + + + Jami is free software for universal communication which respects the freedoms and privacy of its users. + + + + + + This is your ID. +Copy and share it with your friends! + + + + + + Show ring ID QR code + + + + + Share ring ID button + + + + + Double-click to copy + + + + + Error while generating QR Code + + + + + + best name + + + + + best Id + + + + + Back to homepage button + + + + + Add to contacts + + + + + Show invites + + + + + Invites + + + + + + Find a new or existing contact + + + + + Wants to talk to you! + + + + + Answer incoming call button + + + + + Ignore incoming call button + + + + + Answer + + + + + Ignore + + + + + Cancel outgoing call + + + + + Cancel + + + + + Start video call + + + + + Start audio call + + + + + Clear conversation + + + + + Remove contact + + + + + Block contact + + + + + Copy number + + + + + Search your received invitations + + + + + Contact me on Jami + + + + + My Id is : + + + + + %1 + %1 is the contact username + + + + + %1 + %1 is the contact unique identifier + + + + + Call incoming from %1 + + + + + DeleteAccountDialog + + + Account deletion + + + + + Do you really want to delete the following account? + + + + + If this account hasn't been exported, or added to another device, it will be irrevocably lost. + + + + + Permanently delete account + + + + + Delete + + + + + Cancel account deletion + + + + + Cancel + + + + + DeviceItemWidget + + + Form + + + + + Device Id + + + + + this device + + + + + InviteButtonsWidget + + + Accept + + + + + Refuse + + + + + Block + + + + + LinkDeviceDialog + + + Dialog + + + + + Enter your account password + + + + + Password + + + + + Ok + + + + + Cancel + + + + + Exporting account + + + + + Your PIN is + + + + + PIN + + + + + This pin and the account password should be entered in your device within 10 minutes. + + + + + Close + + + + + Link Another Device + + + + + Incorrect password + + + + + Something went wrong. +Please try again later. + + + + + MainWindow + + + Settings + + + + + Exit + + + + + About + + + + + Jami + + + + + NameRegistrationDialog + + + Set Registered Name + + + + + Enter your account password + + + + + Password text input + + + + + Password text entry + + + + + Password + + + + + Register + + + + + Cancel + + + + + Registering Name + + + + + Something went wrong + + + + + Close + + + + + Incorrect password + + + + + Network error + + + + + NewWizardWidget + + + Form + + + + + Welcome Label + + + + + Welcome to + + + + + Welcome Logo + + + + + Create Jami account button + + + + + Push button for Jami account creation start trigger + + + + + Create a Jami account + + + + + Link device button + + + + + Push button for device linkage start trigger + + + + + Link this device to an account + + + + + Create Jami SIP account button + + + + + Push button for Jami SIP account creation start trigger + + + + + Create a SIP account + + + + + Link this device to an existing account + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Ubuntu'; font-size:14px; color:#555555;">To link this device to another account, you first </span><span style=" font-family:'Ubuntu'; font-size:14px; font-weight:600; color:#555555;">need to obtain a PIN</span><span style=" font-family:'Ubuntu'; font-size:14px; color:#555555;"> code. To generate the PIN code:</span></p> +<ol style="margin-top: 0px; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; -qt-list-indent: 1;"><li style=" font-family:'Ubuntu'; font-size:14px; color:#555555;" style=" margin-top:12px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:14px;">Go to the </span><span style=" font-size:14px; font-weight:600;">Account management setting</span><span style=" font-size:14px;"> of a previous device</span></li> +<li style=" font-family:'Ubuntu'; font-size:14px; color:#555555;" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:14px;">Choose the </span><span style=" font-size:14px; font-weight:600;">Jami account</span><span style=" font-size:14px;"> you want to use</span></li> +<li style=" font-family:'Ubuntu'; font-size:14px; color:#555555;" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:14px;">Go to the </span><span style=" font-size:14px; font-weight:600;">Devices</span><span style=" font-size:14px;"> tab</span></li> +<li style=" font-family:'Ubuntu'; font-size:14px; color:#555555;" style=" margin-top:0px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:14px;">Select </span><span style=" font-size:14px; font-weight:600;">Add a device</span></li></ol> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Ubuntu'; font-size:14px; color:#555555;">You will get the necessary PIN to complete this form. The PIN is only valid for </span><span style=" font-family:'Ubuntu'; font-size:14px; font-weight:600; color:#555555;">10 minutes</span><span style=" font-family:'Ubuntu'; font-size:10px; color:#555555;">.</span></p></body></html> + + + + + Enter your pin: + + + + + Or import a file: + + + + + Link from exported account archive file + + + + + + + (None) + + + + + Password: + + + + + + Profile + + + + + + Profile name + + + + + Account + + + + + Register your username. +This will reserve the username so that only you can use it. +Your friends will be able to call you with your usename +instead of using your ID. + + + + + Public username checkbox + + + + + Checkbox selecting if the user wants a public username + + + + + Register public username + + + + + Public username edit + + + + + Choose your username + + + + + Password text input + + + + + Password text entry + + + + + + Password + + + + + + Password confirmation text input + + + + + Confirm password + + + + + SIP Account + + + + + SIP Server edit + + + + + Server + + + + + SIP proxy input + + + + + SIP proxy text entry + + + + + Proxy + + + + + SIP username input + + + + + SIP Password text entry + + + + + Username + + + + + + SIP Password text input + + + + + Generating your Jami account… + + + + + Previous page button + + + + + push button to access previous page of wizard + + + + + Previous + + + + + Cancel account create/link + + + + + push button to cancel account creation or linking + + + + + Back + + + + + Next page Button + + + + + Push button to access next page of wizard + + + + + Next + + + + + Open File + + + + + Jami archive files (*.gz); All files (*) + + + + + Your account needs to be migrated. Enter your password. + + + + + Migrating your Jami account... + + + + + Importing account archive... + + + + + Generating your Jami account... + + + + + Generating your SIP account... + + + + + Error creating account + + + + + PasswordDialog + + + Change Account Password + + + + + Enter Current Password + + + + + Enter New Password + + + + + Confirm New Password + + + + + Confirm + + + + + Cancel + + + + + Current Password Incorrect + + + + + PhotoBoothDialog + + + Photobooth + + + + + PhotoboothWidget + + + Form + + + + + Photobooth display + + + + + Choose File + + + + + Image Files (*.jpg *.jpeg *.png) + + + + + PrivateBridging + + + Choose File + + + + + Files (*) + + + + + QObject + + + No default mail client found + + + + + + Edit Device Name + + + + + Unlink Device From Account + + + + + Save new device name + + + + + Add as contact + + + + + RingButton + + + Select folder + + + + + SettingsWidget + + + Form + + + + + Settings + + + + + Account + + + + + + General + பொது + + + + + Audio / Video + + + + + System + + + + + Enable desktop notifications + + + + + Keep minimized on close + + + + + Download folder + + + + + Save in + + + + + Always Recording + + + + + Updates + + + + + Check for updates automatically every + + + + + Interval between update checks in days selector + + + + + days + + + + + Check for updates now button + + + + + Check for updates now + + + + + Password + + + + + + Enable + + + + + toggle enable notifications + + + + + Toggle keep minimized on close + + + + + Call Recordings + + + + + Toggle automatic updates + + + + + Jami Account + + + + + + Profile + + + + + + Identity + + + + + Id + + + + + Registered name + + + + + Type here to register a username + + + + + Register + + + + + Change Password + + + + + Export Account + + + + + + Delete Account + + + + + Linked Devices + + + + + Link Another Device + + + + + Banned Contacts + + + + + Format + + + + + Video device framerate selector + + + + + Preview unavailable + + + + + + Advanced Account Settings + + + + + SIP Account + + + + + Username + + + + + Hostname + + + + + Proxy + + + + + Audio + கேள்விமாற்றி + + + + Microphone + + + + + Audio input device selector + + + + + Output Device + + + + + Choose the output device + + + + + Video + காணொளி + + + + Device + + + + + Video device selector + + + + + A registered name should not have any spaces and must be at least three letters long + + + + + This name is already taken + + + + + + Enter an alias + + + + + Register this name + + + + + Remove Device + + + + + Enter this account's password to confirm the removal of this device + + + + + Are you sure you wish to remove this device? + + + + + Export Account Here + + + + + Select A Folder For Your Downloads + + + + + Select A Folder For Your Recordings + + + + + VideoOverlay + + + Call on Hold + + + + + Hold / Unhold + + + + + Chat + + + + + Mute Mic + + + + + Record call + + + + + Name label + + + + + Time elapsed + + + + + 00:00 + + + + + Hangup + + + + + Mute Video + + + + + VideoView + + + Share entire screen + + + + + Share screen area + + + + + Share file + + + + \ No newline at end of file diff --git a/translations/ring_client_windows_tr.ts b/translations/ring_client_windows_tr.ts new file mode 100644 index 00000000..65d7db15 --- /dev/null +++ b/translations/ring_client_windows_tr.ts @@ -0,0 +1,1605 @@ + + + AboutDialog + + + + About + Hakkında + + + + about button + hakkında butonu + + + + credits button + kredi butonu + + + + Credits + Krediler + + + + Free as in Freedom + Özgürlükteki gibi ücretsiz + + + + The Microsoft Windows client for Jami. +Jami is a secured and distributed communication software. + Jami için Microsoft Windows istemcisi. +Jami güvenli ve dağıtık bir iletişim yazılımıdır. + + + + version + sürüm + + + + Created by: + Oluşturanlar: + + + + Artwork by: + Çizenler: + + + + Based on the SFLPhone project + SFLPhone tasarısı temel alınmıştır. + + + + AccountItemDelegate + + + Add Account + Hesap Ekle + + + + AdvancedSIPSettingsWidget + + + Form + Form + + + + Call Settings + Arama Ayarları + + + + Auto Answer Calls + Aramaları otomatik yanıtla + + + + Enable Custom Ringtone + Özel zil sesini etkinleştir + + + + Connectivity + Bağlanabilirlik + + + + STUN Address + STUN Adresi + + + + Use STUN + STUN kullan + + + + Use UPnP + UpnP kullan + + + + Use TURN + TURN kullan + + + + TURN Password + TURN Parolası + + + + TURN Username + TURN Kullanıcı Adı + + + + TURN Address + TURN Adresi + + + + Media + Ortam + + + + Enable Video + Görüntüyü Etkinleştir + + + + Video Codecs + Görüntü çözücüler + + + + Audio Codecs + Ses çözücüleri + + + + Audio Files (*.wav *.ogg *.opus *.mp3 *aiff *wma) + Ses Dosyaları (*.wav *.ogg *.opus *.mp3 *aiff *wma) + + + + Add a custom ringtone + Özel bir zil sesi ekle + + + + AdvancedSettingsWidget + + + Form + Form + + + + Call Settings + Arama Ayarları + + + + Allow Calls From Untrusted Peers + Güvenilmeyen Eşlerden Gelen Aramalara İzin Ver + + + + Auto Answer Calls + Aramaları otomatik yanıtla + + + + Enable Custom Ringtone + Özel zil sesini etkinleştir + + + + Add a custom ringtone + Özel bir zil sesi ekle + + + + Name Server + Ad Sunucusu + + + + Address + Yer + + + + OpenDHT Configuration + OpenDHT Yapılandırması + + + + Enable Proxy + Vekil sunucuyu etkinleştir + + + + Bootstrap + Önyükleme + + + + Security + Güvenlik + + + + Private Key Password + Özel Anahtar Parolası + + + + User Certificate + Kullanıcı Sertifikası + + + + Private Key + Özel Anahtar + + + + CA Certificate + CA sertifikası + + + + Connectivity + Bağlanabilirlik + + + + Use STUN + STUN kullan + + + + STUN Address + STUN Adresi + + + + Use UPnP + UpnP kullan + + + + Use TURN + TURN kullan + + + + TURN Password + TURN Parolası + + + + TURN Username + TURN Kullanıcı Adı + + + + TURN Address + TURN Adresi + + + + Media + Ortam + + + + Enable Video + Görüntüyü Etkinleştir + + + + Audio Codecs + Ses çözücüleri + + + + Video Codecs + Görüntü çözücüler + + + + Audio Files (*.wav *.ogg *.opus *.mp3 *aiff *wma) + Ses Dosyaları (*.wav *.ogg *.opus *.mp3 *aiff *wma) + + + + AnimatedOverlay + + + Form + Form + + + + BannedItemWidget + + + Form + Form + + + + name + isim + + + + id + kimlik + + + + CallWidget + + + Show conversations + Konuşmaları göster + + + + Conversations + Konuşmalar + + + + Search contact text input + Kişi ara + + + + Jami is free software for universal communication which respects the freedoms and privacy of its users. + Jami, kullanıcılarının özgürlüklerine ve gizliliğine önem veren, evrensel iletişim için özgür yazılımdır. + + + + + This is your ID. +Copy and share it with your friends! + + + Bu sizin kimliğiniz. +Kopyalayın ve arkadaşlarınızla paylaşın! + + + + Show ring ID QR code + Ring kimliği QR kodunu göster + + + + Share ring ID button + Ring kimliği düğmesini paylaş + + + + Double-click to copy + Kopyalamak için çift tıkla + + + + Error while generating QR Code + QR Kodu oluşturulurken hata + + + + + best name + en iyi ad + + + + best Id + en iyi kimlik + + + + Back to homepage button + Anasayfaya dön düğmesi + + + + Add to contacts + Kişilere ekle + + + + Show invites + Davetleri göster + + + + Invites + Davetler + + + + + Find a new or existing contact + Yeni veya mevcut bir kişiyi bulun + + + + Wants to talk to you! + Sizinle konuşmak istiyor! + + + + Answer incoming call button + Gelen aramayı yanıtla düğmesi + + + + Ignore incoming call button + Gelen arama düğmesini yoksay + + + + Answer + Yanıtla + + + + Ignore + Göz ardı et + + + + Cancel outgoing call + Giden aramayı iptal et + + + + Cancel + İptal + + + + Start video call + Görüntülü arama başlat + + + + Start audio call + Sesli arama başlat + + + + Clear conversation + Konuşmayı temizle + + + + Remove contact + Kişiyi kaldır + + + + Block contact + Kişiyi engelle + + + + Copy number + Numarayı kopyala + + + + Search your received invitations + Aldığınız davetiyeleri arayın + + + + Contact me on Jami + Jami'de bana ulaşın + + + + My Id is : + Kimliğim : + + + + %1 + %1 is the contact username + %1 + + + + %1 + %1 is the contact unique identifier + %1 + + + + Call incoming from %1 + %1$s'dan gelen arama + + + + DeleteAccountDialog + + + Account deletion + Hesap silme + + + + Do you really want to delete the following account? + Aşağıdaki hesabı gerçekten silmek istiyor musunuz? + + + + If this account hasn't been exported, or added to another device, it will be irrevocably lost. + Bu hesap dışa aktarılmadıysa veya başka bir cihaza eklenmediyse, geri döndürülemez şekilde kaybolacaktır. + + + + Permanently delete account + Hesabı kalıcı olarak sil + + + + Delete + Sil + + + + Cancel account deletion + Hesap silmeyi iptal et + + + + Cancel + İptal + + + + DeviceItemWidget + + + Form + Form + + + + Device Id + Aygıt Kimliği + + + + this device + bu aygıt + + + + InviteButtonsWidget + + + Accept + Kabul et + + + + Refuse + Geri Çevir + + + + Block + Engelleme + + + + LinkDeviceDialog + + + Dialog + Karşılıklı konuşma + + + + Enter your account password + Hesap şifrenizi girin + + + + Password + Parola + + + + Ok + Tamam + + + + Cancel + İptal + + + + Exporting account + Hesap dışa aktarılıyor + + + + Your PIN is + PIN kodunuz + + + + PIN + PIN + + + + This pin and the account password should be entered in your device within 10 minutes. + Bu pin ve hesap şifresi 10 dakika içinde cihazınıza girilmelidir. + + + + Close + Kapat + + + + Link Another Device + Diğer aygıtı bağla + + + + Incorrect password + Geçersiz parola + + + + Something went wrong. +Please try again later. + Bir şeyler yanlış gitt. +Lütfen daha sonra yeniden deneyin. + + + + MainWindow + + + Settings + Ayarlar + + + + Exit + Çıkış + + + + About + Hakkında + + + + Jami + Jami + + + + NameRegistrationDialog + + + Set Registered Name + Kayıtlı Adı Ayarla + + + + Enter your account password + Hesap şifrenizi girin + + + + Password text input + Şifre metin girişi + + + + Password text entry + Şifre metin girişi + + + + Password + Parola + + + + Register + Kaydol + + + + Cancel + İptal + + + + Registering Name + Kayıt Adı + + + + Something went wrong + Bir şeyler yanlış gitti + + + + Close + Kapat + + + + Incorrect password + Geçersiz parola + + + + Network error + Ağ hatası + + + + NewWizardWidget + + + Form + Form + + + + Welcome Label + Hoşgeldin Etiketi + + + + Welcome to + Hoş Geldiniz + + + + Welcome Logo + Hoşgeldin Logosu + + + + Create Jami account button + Jami hesabı düğmesi oluştur + + + + Push button for Jami account creation start trigger + Jami hesabı oluşturma başlatma tetikleyicisi için basma düğmesi + + + + Create a Jami account + Bir Jami hesabı oluştur + + + + Link device button + Aygıt bağla düğmesi + + + + Push button for device linkage start trigger + Jami hesabı oluşturma başlatma tetikleyicisi için basınız + + + + Link this device to an account + Bu aygıtı bir hesaba bağla + + + + Create Jami SIP account button + Jami SIP hesabı oluştur düğmesi + + + + Push button for Jami SIP account creation start trigger + Jami SIP hesabı oluşturma başlatma tetikleyicisi için basınız + + + + Create a SIP account + Bir SIP hesabı oluşturun + + + + Link this device to an existing account + Bu aygıtı var olan bir hesaba bağla + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Ubuntu'; font-size:14px; color:#555555;">To link this device to another account, you first </span><span style=" font-family:'Ubuntu'; font-size:14px; font-weight:600; color:#555555;">need to obtain a PIN</span><span style=" font-family:'Ubuntu'; font-size:14px; color:#555555;"> code. To generate the PIN code:</span></p> +<ol style="margin-top: 0px; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; -qt-list-indent: 1;"><li style=" font-family:'Ubuntu'; font-size:14px; color:#555555;" style=" margin-top:12px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:14px;">Go to the </span><span style=" font-size:14px; font-weight:600;">Account management setting</span><span style=" font-size:14px;"> of a previous device</span></li> +<li style=" font-family:'Ubuntu'; font-size:14px; color:#555555;" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:14px;">Choose the </span><span style=" font-size:14px; font-weight:600;">Jami account</span><span style=" font-size:14px;"> you want to use</span></li> +<li style=" font-family:'Ubuntu'; font-size:14px; color:#555555;" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:14px;">Go to the </span><span style=" font-size:14px; font-weight:600;">Devices</span><span style=" font-size:14px;"> tab</span></li> +<li style=" font-family:'Ubuntu'; font-size:14px; color:#555555;" style=" margin-top:0px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:14px;">Select </span><span style=" font-size:14px; font-weight:600;">Add a device</span></li></ol> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Ubuntu'; font-size:14px; color:#555555;">You will get the necessary PIN to complete this form. The PIN is only valid for </span><span style=" font-family:'Ubuntu'; font-size:14px; font-weight:600; color:#555555;">10 minutes</span><span style=" font-family:'Ubuntu'; font-size:10px; color:#555555;">.</span></p></body></html> + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Ubuntu'; font-size:14px; color:#555555;">Bu cihazı başka bir hesapla eşlemek için, önce </span><span style=" font-family:'Ubuntu'; font-size:14px; font-weight:600; color:#555555;"> PIN edinmeniz gerekir</span><span style=" font-family:'Ubuntu'; font-size:14px; color:#555555;"> PIN kodu edinmek için:</span></p> +<ol style="margin-top: 0px; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; -qt-list-indent: 1;"><li style=" font-family:'Ubuntu'; font-size:14px; color:#555555;" style=" margin-top:12px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:14px;">Bir önceki </span><span style=" font-size:14px; font-weight:600;">cihazınızdaki hesap ayarları</span><span style=" font-size:14px;"> yönetimine gidin</span></li> +<li style=" font-family:'Ubuntu'; font-size:14px; color:#555555;" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:14px;">İstediğiniz </span><span style=" font-size:14px; font-weight:600;">Jami hesabını</span><span style=" font-size:14px;"> seçin</span></li> +<li style=" font-family:'Ubuntu'; font-size:14px; color:#555555;" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:14px;">Cihazlar </span><span style=" font-size:14px; font-weight:600;">sekmesine </span><span style=" font-size:14px;"> gidin </li> +<li style=" font-family:'Ubuntu'; font-size:14px; color:#555555;" style=" margin-top:0px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:14px;">Cihaz </span><span style=" font-size:14px; font-weight:600;"> Ekleyi seçin</span></li></ol> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Ubuntu'; font-size:14px; color:#555555;">Bu formu doldurmak için gerekli PIN kodunu alacaksınız. Bu PIN sadece </span><span style=" font-family:'Ubuntu'; font-size:14px; font-weight:600; color:#555555;">10 dakika geçerlidir.</span><span style=" font-family:'Ubuntu'; font-size:10px; color:#555555;">.</span></p></body></html> + + + + Enter your pin: + Pin'inizi girin: + + + + Or import a file: + veya bir dosya içe aktar + + + + Link from exported account archive file + Dışa aktarılan hesap arşiv dosyasından bağlantı + + + + + + (None) + (Hiçbiri) + + + + Password: + Parola: + + + + + Profile + Profil + + + + + Profile name + Profil adı + + + + Account + Hesap + + + + Register your username. +This will reserve the username so that only you can use it. +Your friends will be able to call you with your usename +instead of using your ID. + Kullanıcı adınızı kaydedin. +Bu, yalnızca siz kullanabilmeniz için kullanıcı adını ayıracaktır. +Arkadaşlarınız kimliğinizi kullanmak yerine +kullanıcı adınızla sizi arayabilecek. + + + + Public username checkbox + Herkese açık kullanıcı adı onay kutusu + + + + Checkbox selecting if the user wants a public username + Kullanıcının herkese açık bir kullanıcı adı isteyip istemediğini seçme onay kutusu + + + + Register public username + Halka açık kullanıcı adı kaydet + + + + Public username edit + Herkese açık kullanıcı adı düzenleme + + + + Choose your username + Kullanıcı adınızı seçin + + + + Password text input + Şifre metin girişi + + + + Password text entry + Şifre metin girişi + + + + + Password + Parola + + + + + Password confirmation text input + Şifre onay metni girişi + + + + Confirm password + Parolayı onayla + + + + SIP Account + SIP Hesabı + + + + SIP Server edit + SIP Sunucusu düzenleme + + + + Server + Sunucu + + + + SIP proxy input + SIP proxy girişi + + + + SIP proxy text entry + SIP proxy metin girişi + + + + Proxy + Vekil + + + + SIP username input + SIP kullanıcı adı girişi + + + + SIP Password text entry + SIP Parolası metin girişi + + + + Username + Kullanıcı adı + + + + + SIP Password text input + SIP Şifre metin girişi + + + + Generating your Jami account… + Jami hesabınız oluşturuluyor... + + + + Previous page button + Önceki sayfa düğmesi + + + + push button to access previous page of wizard + sihirbazın önceki sayfasına erişmek için düğmeye basın + + + + Previous + Önceki + + + + Cancel account create/link + Hesap oluşturmayı / bağlantıyı iptal et + + + + push button to cancel account creation or linking + hesap oluşturmayı veya bağlamayı iptal etmek için düğmeye basın + + + + Back + Geri + + + + Next page Button + Sonraki sayfa düğmesi + + + + Push button to access next page of wizard + Sihirbazın sonraki sayfasına erişmek için düğmeye basın + + + + Next + İleri + + + + Open File + Dosyayı Aç + + + + Jami archive files (*.gz); All files (*) + Jami arşiv dosyaları (*.gz); Tüm Dosyalar (*) + + + + Your account needs to be migrated. Enter your password. + Hesabınızın taşınması gerekiyor. Parolanızı girin. + + + + Migrating your Jami account... + Jami hesabınız göç ettiriliyor... + + + + Importing account archive... + Hesap arşivi içe aktarılıyor... + + + + Generating your Jami account... + Jami hesabınız oluşturuluyor... + + + + Generating your SIP account... + SIP hesabınız oluşturuluyor ... + + + + Error creating account + Hesap oluşturma hatası + + + + PasswordDialog + + + Change Account Password + Hesap Parolasını Değiştir + + + + Enter Current Password + Şimdiki Parolayı Girin + + + + Enter New Password + Yeni Parolayı Girin + + + + Confirm New Password + Yeni Parolayı Doğrulayın + + + + Confirm + Onayla + + + + Cancel + İptal + + + + Current Password Incorrect + Kullanılan Parola Hatalı + + + + PhotoBoothDialog + + + Photobooth + Fotoğraf kabini + + + + PhotoboothWidget + + + Form + Form + + + + Photobooth display + Fotoğraf kabini görüntüsü + + + + Choose File + Dosya Seç + + + + Image Files (*.jpg *.jpeg *.png) + Resim Dosyaları (*.jpg *.jpeg *.png) + + + + PrivateBridging + + + Choose File + Dosya Seç + + + + Files (*) + Dosyalar (*) + + + + QObject + + + No default mail client found + Varsayılan posta istemcisi bulunmadı + + + + + Edit Device Name + Aygıt Adını Düzenle + + + + Unlink Device From Account + Aygıtın Hesaptan Bağlantısını Kaldır + + + + Save new device name + Yeni cihaz adını kaydet + + + + Add as contact + Kişi listesine ekle + + + + RingButton + + + Select folder + Klasör seç + + + + SettingsWidget + + + Form + Form + + + + Settings + Ayarlar + + + + Account + Hesap + + + + + General + Genel + + + + + Audio / Video + Ses / Görüntü + + + + System + Düzen + + + + Enable desktop notifications + Masaüstü bildirimlerini etkinleştir + + + + Keep minimized on close + Kapatırken küçültülmüş olarak tut + + + + Download folder + İndirme klasörü + + + + Save in + Kaydet + + + + Always Recording + Devamlı kaydediliyor + + + + Updates + Güncellemeler + + + + Check for updates automatically every + Güncellemeleri kendiliğinden denetle + + + + Interval between update checks in days selector + Gün seçicideki güncelleme denetimleri aralığı + + + + days + gün + + + + Check for updates now button + Şimdi güncellemeleri denetle düğmesi + + + + Check for updates now + Şimdi güncellemeleri denetle + + + + Password + Parola + + + + + Enable + Etkin + + + + toggle enable notifications + bildirimleri etkinleştirmeyi aç / kapat + + + + Toggle keep minimized on close + Kapatırken simge durumuna küçültmeyi aç / kapat + + + + Call Recordings + Çağrı Kayıtları + + + + Toggle automatic updates + Otomatik güncellemeleri aç / kapat + + + + Jami Account + Jami Hesabı + + + + + Profile + Profil + + + + + Identity + Kimlik + + + + Id + Kimlik + + + + Registered name + Kaydedilen ad + + + + Type here to register a username + Bir kullanıcı adı kaydetmek için buraya yazın + + + + Register + Kaydol + + + + Change Password + Parolayı Değiştir + + + + Export Account + Hesabı Dışa Aktar + + + + + Delete Account + Hesabı Sil + + + + Linked Devices + Bağlı Aygıtlar + + + + Link Another Device + Diğer aygıtı bağla + + + + Banned Contacts + Engellenmiş Kişiler + + + + Format + Biçim + + + + Video device framerate selector + Video cihazı kare hızı seçici + + + + Preview unavailable + Önizleme kullanılamıyor + + + + + Advanced Account Settings + Gelişmiş Hesap ayarları + + + + SIP Account + SIP Hesabı + + + + Username + Kullanıcı adı + + + + Hostname + Sunucu adı + + + + Proxy + Vekil + + + + Audio + Ses + + + + Microphone + Mikrofon + + + + Audio input device selector + Ses giriş aygıtı seçici + + + + Output Device + Çıkış Aygıtı + + + + Choose the output device + Çıkış aygıtını seç + + + + Video + Görüntü + + + + Device + Aygıt + + + + Video device selector + Görüntü aygıtı seçici + + + + A registered name should not have any spaces and must be at least three letters long + Kayıtlı bir isim hiç boşluk bırakmamalı ve en az üç harf uzunluğunda olmalıdır. + + + + This name is already taken + Bu ad önceden alınmış + + + + + Enter an alias + Bir takma ad girin + + + + Register this name + Bu adı kaydet + + + + Remove Device + Aygıtı Kaldır + + + + Enter this account's password to confirm the removal of this device + Bu aygıtın kaldırılmasını onaylamak için bu hesabın şifresini girin. + + + + Are you sure you wish to remove this device? + Bu cihazı kaldırmak istediğinizden emin misiniz? + + + + Export Account Here + Hesabı Buraya Dışa Aktar + + + + Select A Folder For Your Downloads + İndirmeleriniz İçin Bir Klasör Seçin + + + + Select A Folder For Your Recordings + Kayıtlarınız İçin Bir Klasör Seçin + + + + VideoOverlay + + + Call on Hold + Çağrı Beklemede + + + + Hold / Unhold + Beklet / Bekletmeyi kaldır + + + + Chat + Sohbet + + + + Mute Mic + Mikrofonu kapat + + + + Record call + Çağrıyı kaydet + + + + Name label + İsim etiketi + + + + Time elapsed + Geçen zaman + + + + 00:00 + 00:00 + + + + Hangup + Kapat + + + + Mute Video + Görüntüyü kapat + + + + VideoView + + + Share entire screen + Tüm ekranı paylaş + + + + Share screen area + Ekran alanı paylaş + + + + Share file + Dosya paylaş + + + \ No newline at end of file diff --git a/translations/ring_client_windows_tr_TR.ts b/translations/ring_client_windows_tr_TR.ts new file mode 100644 index 00000000..06e7fb97 --- /dev/null +++ b/translations/ring_client_windows_tr_TR.ts @@ -0,0 +1,1589 @@ + + + AboutDialog + + + + About + + + + + about button + + + + + credits button + + + + + Credits + Emek verenler + + + + Free as in Freedom + + + + + The Microsoft Windows client for Jami. +Jami is a secured and distributed communication software. + + + + + version + + + + + Created by: + + + + + Artwork by: + + + + + Based on the SFLPhone project + + + + + AccountItemDelegate + + + Add Account + + + + + AdvancedSIPSettingsWidget + + + Form + + + + + Call Settings + + + + + Auto Answer Calls + + + + + Enable Custom Ringtone + + + + + Connectivity + + + + + STUN Address + + + + + Use STUN + + + + + Use UPnP + + + + + Use TURN + + + + + TURN Password + + + + + TURN Username + + + + + TURN Address + + + + + Media + + + + + Enable Video + + + + + Video Codecs + + + + + Audio Codecs + + + + + Audio Files (*.wav *.ogg *.opus *.mp3 *aiff *wma) + + + + + Add a custom ringtone + + + + + AdvancedSettingsWidget + + + Form + + + + + Call Settings + + + + + Allow Calls From Untrusted Peers + + + + + Auto Answer Calls + + + + + Enable Custom Ringtone + + + + + Add a custom ringtone + + + + + Name Server + + + + + Address + + + + + OpenDHT Configuration + + + + + Enable Proxy + + + + + Bootstrap + + + + + Security + + + + + Private Key Password + + + + + User Certificate + + + + + Private Key + + + + + CA Certificate + + + + + Connectivity + + + + + Use STUN + + + + + STUN Address + + + + + Use UPnP + + + + + Use TURN + + + + + TURN Password + + + + + TURN Username + + + + + TURN Address + + + + + Media + + + + + Enable Video + + + + + Audio Codecs + + + + + Video Codecs + + + + + Audio Files (*.wav *.ogg *.opus *.mp3 *aiff *wma) + + + + + AnimatedOverlay + + + Form + + + + + BannedItemWidget + + + Form + + + + + name + + + + + id + + + + + CallWidget + + + Show conversations + + + + + Conversations + + + + + Search contact text input + + + + + Jami is free software for universal communication which respects the freedoms and privacy of its users. + + + + + + This is your ID. +Copy and share it with your friends! + + + + + + Show ring ID QR code + + + + + Share ring ID button + + + + + Double-click to copy + + + + + Error while generating QR Code + + + + + + best name + + + + + best Id + + + + + Back to homepage button + + + + + Add to contacts + + + + + Show invites + + + + + Invites + + + + + + Find a new or existing contact + + + + + Wants to talk to you! + + + + + Answer incoming call button + + + + + Ignore incoming call button + + + + + Answer + + + + + Ignore + + + + + Cancel outgoing call + + + + + Cancel + + + + + Start video call + + + + + Start audio call + + + + + Clear conversation + + + + + Remove contact + + + + + Block contact + + + + + Copy number + + + + + Search your received invitations + + + + + Contact me on Jami + + + + + My Id is : + + + + + %1 + %1 is the contact username + + + + + %1 + %1 is the contact unique identifier + + + + + Call incoming from %1 + + + + + DeleteAccountDialog + + + Account deletion + + + + + Do you really want to delete the following account? + + + + + If this account hasn't been exported, or added to another device, it will be irrevocably lost. + + + + + Permanently delete account + + + + + Delete + + + + + Cancel account deletion + + + + + Cancel + + + + + DeviceItemWidget + + + Form + + + + + Device Id + + + + + this device + + + + + InviteButtonsWidget + + + Accept + + + + + Refuse + + + + + Block + + + + + LinkDeviceDialog + + + Dialog + + + + + Enter your account password + + + + + Password + + + + + Ok + + + + + Cancel + + + + + Exporting account + + + + + Your PIN is + + + + + PIN + + + + + This pin and the account password should be entered in your device within 10 minutes. + + + + + Close + + + + + Link Another Device + + + + + Incorrect password + + + + + Something went wrong. +Please try again later. + + + + + MainWindow + + + Settings + Ayarlar + + + + Exit + + + + + About + + + + + Jami + + + + + NameRegistrationDialog + + + Set Registered Name + + + + + Enter your account password + + + + + Password text input + + + + + Password text entry + + + + + Password + + + + + Register + + + + + Cancel + + + + + Registering Name + + + + + Something went wrong + + + + + Close + + + + + Incorrect password + + + + + Network error + + + + + NewWizardWidget + + + Form + + + + + Welcome Label + + + + + Welcome to + + + + + Welcome Logo + + + + + Create Jami account button + + + + + Push button for Jami account creation start trigger + + + + + Create a Jami account + + + + + Link device button + + + + + Push button for device linkage start trigger + + + + + Link this device to an account + + + + + Create Jami SIP account button + + + + + Push button for Jami SIP account creation start trigger + + + + + Create a SIP account + + + + + Link this device to an existing account + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Ubuntu'; font-size:14px; color:#555555;">To link this device to another account, you first </span><span style=" font-family:'Ubuntu'; font-size:14px; font-weight:600; color:#555555;">need to obtain a PIN</span><span style=" font-family:'Ubuntu'; font-size:14px; color:#555555;"> code. To generate the PIN code:</span></p> +<ol style="margin-top: 0px; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; -qt-list-indent: 1;"><li style=" font-family:'Ubuntu'; font-size:14px; color:#555555;" style=" margin-top:12px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:14px;">Go to the </span><span style=" font-size:14px; font-weight:600;">Account management setting</span><span style=" font-size:14px;"> of a previous device</span></li> +<li style=" font-family:'Ubuntu'; font-size:14px; color:#555555;" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:14px;">Choose the </span><span style=" font-size:14px; font-weight:600;">Jami account</span><span style=" font-size:14px;"> you want to use</span></li> +<li style=" font-family:'Ubuntu'; font-size:14px; color:#555555;" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:14px;">Go to the </span><span style=" font-size:14px; font-weight:600;">Devices</span><span style=" font-size:14px;"> tab</span></li> +<li style=" font-family:'Ubuntu'; font-size:14px; color:#555555;" style=" margin-top:0px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:14px;">Select </span><span style=" font-size:14px; font-weight:600;">Add a device</span></li></ol> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Ubuntu'; font-size:14px; color:#555555;">You will get the necessary PIN to complete this form. The PIN is only valid for </span><span style=" font-family:'Ubuntu'; font-size:14px; font-weight:600; color:#555555;">10 minutes</span><span style=" font-family:'Ubuntu'; font-size:10px; color:#555555;">.</span></p></body></html> + + + + + Enter your pin: + + + + + Or import a file: + + + + + Link from exported account archive file + + + + + + + (None) + + + + + Password: + + + + + + Profile + + + + + + Profile name + + + + + Account + + + + + Register your username. +This will reserve the username so that only you can use it. +Your friends will be able to call you with your usename +instead of using your ID. + + + + + Public username checkbox + + + + + Checkbox selecting if the user wants a public username + + + + + Register public username + + + + + Public username edit + + + + + Choose your username + + + + + Password text input + + + + + Password text entry + + + + + + Password + + + + + + Password confirmation text input + + + + + Confirm password + + + + + SIP Account + + + + + SIP Server edit + + + + + Server + + + + + SIP proxy input + + + + + SIP proxy text entry + + + + + Proxy + + + + + SIP username input + + + + + SIP Password text entry + + + + + Username + + + + + + SIP Password text input + + + + + Generating your Jami account… + + + + + Previous page button + + + + + push button to access previous page of wizard + + + + + Previous + + + + + Cancel account create/link + + + + + push button to cancel account creation or linking + + + + + Back + + + + + Next page Button + + + + + Push button to access next page of wizard + + + + + Next + + + + + Open File + + + + + Jami archive files (*.gz); All files (*) + + + + + Your account needs to be migrated. Enter your password. + + + + + Migrating your Jami account... + + + + + Importing account archive... + + + + + Generating your Jami account... + + + + + Generating your SIP account... + + + + + Error creating account + + + + + PasswordDialog + + + Change Account Password + + + + + Enter Current Password + + + + + Enter New Password + + + + + Confirm New Password + + + + + Confirm + + + + + Cancel + + + + + Current Password Incorrect + + + + + PhotoBoothDialog + + + Photobooth + + + + + PhotoboothWidget + + + Form + + + + + Photobooth display + + + + + Choose File + + + + + Image Files (*.jpg *.jpeg *.png) + + + + + PrivateBridging + + + Choose File + + + + + Files (*) + + + + + QObject + + + No default mail client found + + + + + + Edit Device Name + + + + + Unlink Device From Account + + + + + Save new device name + + + + + Add as contact + + + + + RingButton + + + Select folder + + + + + SettingsWidget + + + Form + + + + + Settings + Ayarlar + + + + Account + + + + + + General + + + + + + Audio / Video + + + + + System + + + + + Enable desktop notifications + + + + + Keep minimized on close + + + + + Download folder + + + + + Save in + + + + + Always Recording + + + + + Updates + + + + + Check for updates automatically every + + + + + Interval between update checks in days selector + + + + + days + + + + + Check for updates now button + + + + + Check for updates now + + + + + Password + + + + + + Enable + + + + + toggle enable notifications + + + + + Toggle keep minimized on close + + + + + Call Recordings + + + + + Toggle automatic updates + + + + + Jami Account + + + + + + Profile + + + + + + Identity + + + + + Id + + + + + Registered name + + + + + Type here to register a username + + + + + Register + + + + + Change Password + + + + + Export Account + + + + + + Delete Account + + + + + Linked Devices + + + + + Link Another Device + + + + + Banned Contacts + + + + + Format + + + + + Video device framerate selector + + + + + Preview unavailable + + + + + + Advanced Account Settings + + + + + SIP Account + + + + + Username + + + + + Hostname + + + + + Proxy + + + + + Audio + + + + + Microphone + + + + + Audio input device selector + + + + + Output Device + + + + + Choose the output device + + + + + Video + + + + + Device + + + + + Video device selector + + + + + A registered name should not have any spaces and must be at least three letters long + + + + + This name is already taken + + + + + + Enter an alias + + + + + Register this name + + + + + Remove Device + + + + + Enter this account's password to confirm the removal of this device + + + + + Are you sure you wish to remove this device? + + + + + Export Account Here + + + + + Select A Folder For Your Downloads + + + + + Select A Folder For Your Recordings + + + + + VideoOverlay + + + Call on Hold + + + + + Hold / Unhold + + + + + Chat + + + + + Mute Mic + + + + + Record call + + + + + Name label + + + + + Time elapsed + + + + + 00:00 + + + + + Hangup + + + + + Mute Video + + + + + VideoView + + + Share entire screen + + + + + Share screen area + + + + + Share file + + + + \ No newline at end of file diff --git a/translations/ring_client_windows_uk.ts b/translations/ring_client_windows_uk.ts new file mode 100644 index 00000000..c083d3cc --- /dev/null +++ b/translations/ring_client_windows_uk.ts @@ -0,0 +1,1599 @@ + + + AboutDialog + + + + About + Про программу + + + + about button + кнопка про програму + + + + credits button + + + + + Credits + Подяки + + + + Free as in Freedom + + + + + The Microsoft Windows client for Jami. +Jami is a secured and distributed communication software. + Клієнт Джамі для Microsoft Windows. +Джамі — це безпечне розподілене програмне забезпечення для зв'язку. + + + + version + версія + + + + Created by: + Стоворено: + + + + Artwork by: + Намальовано: + + + + Based on the SFLPhone project + Базується на проекті SFLPhone + + + + AccountItemDelegate + + + Add Account + + + + + AdvancedSIPSettingsWidget + + + Form + Форма + + + + Call Settings + + + + + Auto Answer Calls + Приймати дзвінки автоматично + + + + Enable Custom Ringtone + + + + + Connectivity + З'єднання + + + + STUN Address + + + + + Use STUN + Використовувати STUN + + + + Use UPnP + + + + + Use TURN + Використовувати TURN + + + + TURN Password + + + + + TURN Username + + + + + TURN Address + + + + + Media + Медіа + + + + Enable Video + Увімкнути відео + + + + Video Codecs + + + + + Audio Codecs + + + + + Audio Files (*.wav *.ogg *.opus *.mp3 *aiff *wma) + + + + + Add a custom ringtone + + + + + AdvancedSettingsWidget + + + Form + Форма + + + + Call Settings + + + + + Allow Calls From Untrusted Peers + + + + + Auto Answer Calls + Приймати дзвінки автоматично + + + + Enable Custom Ringtone + + + + + Add a custom ringtone + + + + + Name Server + + + + + Address + Адреса + + + + OpenDHT Configuration + + + + + Enable Proxy + + + + + Bootstrap + Початкове завантаження + + + + Security + Безпека + + + + Private Key Password + Пароль від приватного ключа + + + + User Certificate + Сертифікат користувача + + + + Private Key + + + + + CA Certificate + + + + + Connectivity + З'єднання + + + + Use STUN + Використовувати STUN + + + + STUN Address + + + + + Use UPnP + + + + + Use TURN + Використовувати TURN + + + + TURN Password + + + + + TURN Username + + + + + TURN Address + + + + + Media + Медіа + + + + Enable Video + Увімкнути відео + + + + Audio Codecs + + + + + Video Codecs + + + + + Audio Files (*.wav *.ogg *.opus *.mp3 *aiff *wma) + + + + + AnimatedOverlay + + + Form + Форма + + + + BannedItemWidget + + + Form + Форма + + + + name + + + + + id + + + + + CallWidget + + + Show conversations + + + + + Conversations + Групові чати + + + + Search contact text input + + + + + Jami is free software for universal communication which respects the freedoms and privacy of its users. + Джамі — це вільне програмне забезпечення для будь-якого зв'язку з повагою до свобод і приватності користувачів. + + + + + This is your ID. +Copy and share it with your friends! + + + + + + Show ring ID QR code + + + + + Share ring ID button + + + + + Double-click to copy + Клацніть двічі, щоб скопіювати + + + + Error while generating QR Code + Помилка при генерації QR-коду + + + + + best name + + + + + best Id + + + + + Back to homepage button + + + + + Add to contacts + Додати контакти + + + + Show invites + + + + + Invites + + + + + + Find a new or existing contact + + + + + Wants to talk to you! + Хоче поговорити з вами! + + + + Answer incoming call button + + + + + Ignore incoming call button + Кнопка ігнорування вхідного дзвінка + + + + Answer + Відповідь + + + + Ignore + Ігнорувати + + + + Cancel outgoing call + + + + + Cancel + Відміна + + + + Start video call + + + + + Start audio call + + + + + Clear conversation + + + + + Remove contact + Видалити контакт + + + + Block contact + Заблокувати контакт + + + + Copy number + Копіювати номер + + + + Search your received invitations + + + + + Contact me on Jami + Зв'яжіться зі мною в Джамі + + + + My Id is : + + + + + %1 + %1 is the contact username + %1 + + + + %1 + %1 is the contact unique identifier + %1 + + + + Call incoming from %1 + Вхідний виклик від %1 + + + + DeleteAccountDialog + + + Account deletion + + + + + Do you really want to delete the following account? + + + + + If this account hasn't been exported, or added to another device, it will be irrevocably lost. + + + + + Permanently delete account + + + + + Delete + Видалити + + + + Cancel account deletion + + + + + Cancel + Відміна + + + + DeviceItemWidget + + + Form + Форма + + + + Device Id + + + + + this device + цей пристрій + + + + InviteButtonsWidget + + + Accept + Прийняти + + + + Refuse + Скидання + + + + Block + Заблокувати + + + + LinkDeviceDialog + + + Dialog + Діалог + + + + Enter your account password + + + + + Password + Пароль + + + + Ok + Ок + + + + Cancel + Відміна + + + + Exporting account + Експортувати акаунт + + + + Your PIN is + + + + + PIN + PIN-код + + + + This pin and the account password should be entered in your device within 10 minutes. + + + + + Close + Закрити + + + + Link Another Device + + + + + Incorrect password + + + + + Something went wrong. +Please try again later. + + + + + MainWindow + + + Settings + Налаштування + + + + Exit + Вийти + + + + About + Про программу + + + + Jami + Джамі + + + + NameRegistrationDialog + + + Set Registered Name + + + + + Enter your account password + + + + + Password text input + + + + + Password text entry + + + + + Password + Пароль + + + + Register + Зареєструватися + + + + Cancel + Відміна + + + + Registering Name + + + + + Something went wrong + + + + + Close + Закрити + + + + Incorrect password + + + + + Network error + Збій мережі + + + + NewWizardWidget + + + Form + Форма + + + + Welcome Label + + + + + Welcome to + + + + + Welcome Logo + + + + + Create Jami account button + Кнопка створення облікового запису Джамі + + + + Push button for Jami account creation start trigger + Натисніть кнопку, щоб розпочати створення облікового запису Джамі + + + + Create a Jami account + Створити обліковий запис Джамі + + + + Link device button + + + + + Push button for device linkage start trigger + + + + + Link this device to an account + Прив'язати цей пристрій до облікового запису + + + + Create Jami SIP account button + + + + + Push button for Jami SIP account creation start trigger + + + + + Create a SIP account + + + + + Link this device to an existing account + Зв'язати цей пристрій з наявним обліковим записом + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Ubuntu'; font-size:14px; color:#555555;">To link this device to another account, you first </span><span style=" font-family:'Ubuntu'; font-size:14px; font-weight:600; color:#555555;">need to obtain a PIN</span><span style=" font-family:'Ubuntu'; font-size:14px; color:#555555;"> code. To generate the PIN code:</span></p> +<ol style="margin-top: 0px; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; -qt-list-indent: 1;"><li style=" font-family:'Ubuntu'; font-size:14px; color:#555555;" style=" margin-top:12px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:14px;">Go to the </span><span style=" font-size:14px; font-weight:600;">Account management setting</span><span style=" font-size:14px;"> of a previous device</span></li> +<li style=" font-family:'Ubuntu'; font-size:14px; color:#555555;" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:14px;">Choose the </span><span style=" font-size:14px; font-weight:600;">Jami account</span><span style=" font-size:14px;"> you want to use</span></li> +<li style=" font-family:'Ubuntu'; font-size:14px; color:#555555;" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:14px;">Go to the </span><span style=" font-size:14px; font-weight:600;">Devices</span><span style=" font-size:14px;"> tab</span></li> +<li style=" font-family:'Ubuntu'; font-size:14px; color:#555555;" style=" margin-top:0px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:14px;">Select </span><span style=" font-size:14px; font-weight:600;">Add a device</span></li></ol> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Ubuntu'; font-size:14px; color:#555555;">You will get the necessary PIN to complete this form. The PIN is only valid for </span><span style=" font-family:'Ubuntu'; font-size:14px; font-weight:600; color:#555555;">10 minutes</span><span style=" font-family:'Ubuntu'; font-size:10px; color:#555555;">.</span></p></body></html> + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Ubuntu'; font-size:14px; color:#555555;">Щоб прив'язати цей пристрій до іншого облікового запису, вам, спершу, </span><span style=" font-family:'Ubuntu'; font-size:14px; font-weight:600; color:#555555;">потрібно отримати PIN</span><span style=" font-family:'Ubuntu'; font-size:14px; color:#555555;">-код. Щоб отримати PIN-код:</span></p> +<ol style="margin-top: 0px; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; -qt-list-indent: 1;"><li style=" font-family:'Ubuntu'; font-size:14px; color:#555555;" style=" margin-top:12px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:14px;">Перейдіть до </span><span style=" font-size:14px; font-weight:600;">Налаштування управління обліковим записом</span><span style=" font-size:14px;"> на попередньому пристрої</span></li> +<li style=" font-family:'Ubuntu'; font-size:14px; color:#555555;" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:14px;">Виберіть </span><span style=" font-size:14px; font-weight:600;">обліковий запис Джамі</span><span style=" font-size:14px;"> який ви бажаєте</span></li> +<li style=" font-family:'Ubuntu'; font-size:14px; color:#555555;" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:14px;">Перейдіть до </span><span style=" font-size:14px; font-weight:600;">Пристрої</span><span style=" font-size:14px;"> вкладки</span></li> +<li style=" font-family:'Ubuntu'; font-size:14px; color:#555555;" style=" margin-top:0px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:14px;">Виберіть </span><span style=" font-size:14px; font-weight:600;">Додатки пристрій</span></li></ol> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Ubuntu'; font-size:14px; color:#555555;">Ви отримаєте PIN-код, який потрібно ввести тут. PIN-код дійсний лише протягом </span><span style=" font-family:'Ubuntu'; font-size:14px; font-weight:600; color:#555555;">10 хвилин</span><span style=" font-family:'Ubuntu'; font-size:10px; color:#555555;">.</span></p></body></html> + + + + Enter your pin: + Введіть ваш PIN-код: + + + + Or import a file: + Або завантажте з файлу: + + + + Link from exported account archive file + + + + + + + (None) + + + + + Password: + Пароль: + + + + + Profile + Профіль + + + + + Profile name + + + + + Account + Аккаунт + + + + Register your username. +This will reserve the username so that only you can use it. +Your friends will be able to call you with your usename +instead of using your ID. + + + + + Public username checkbox + + + + + Checkbox selecting if the user wants a public username + + + + + Register public username + Зареєструвати публічне ум'я користувача + + + + Public username edit + + + + + Choose your username + Оберіть ваше ім'я користувача + + + + Password text input + + + + + Password text entry + + + + + + Password + Пароль + + + + + Password confirmation text input + + + + + Confirm password + Підтвердити пароль + + + + SIP Account + Аккаунт SIP + + + + SIP Server edit + + + + + Server + + + + + SIP proxy input + + + + + SIP proxy text entry + + + + + Proxy + Проксі + + + + SIP username input + + + + + SIP Password text entry + + + + + Username + Ім’я + + + + + SIP Password text input + + + + + Generating your Jami account… + Створення вашого облікового запису Джамі… + + + + Previous page button + + + + + push button to access previous page of wizard + + + + + Previous + Попереднє + + + + Cancel account create/link + + + + + push button to cancel account creation or linking + + + + + Back + Назад + + + + Next page Button + + + + + Push button to access next page of wizard + + + + + Next + Далі + + + + Open File + Відкрити файл + + + + Jami archive files (*.gz); All files (*) + Файли архівів Джамі (*.gz); Усі файли (*) + + + + Your account needs to be migrated. Enter your password. + + + + + Migrating your Jami account... + Переведення вашого облікового запису Джамі… + + + + Importing account archive... + + + + + Generating your Jami account... + Створення вашого облікового запису Джамі… + + + + Generating your SIP account... + + + + + Error creating account + + + + + PasswordDialog + + + Change Account Password + + + + + Enter Current Password + + + + + Enter New Password + + + + + Confirm New Password + + + + + Confirm + + + + + Cancel + Відміна + + + + Current Password Incorrect + + + + + PhotoBoothDialog + + + Photobooth + Стенд + + + + PhotoboothWidget + + + Form + Форма + + + + Photobooth display + Показ віконця світлини + + + + Choose File + Вибрати файл + + + + Image Files (*.jpg *.jpeg *.png) + + + + + PrivateBridging + + + Choose File + Вибрати файл + + + + Files (*) + Файли (*) + + + + QObject + + + No default mail client found + Не знайдено жодного поштового клієнту + + + + + Edit Device Name + + + + + Unlink Device From Account + + + + + Save new device name + + + + + Add as contact + + + + + RingButton + + + Select folder + + + + + SettingsWidget + + + Form + Форма + + + + Settings + Налаштування + + + + Account + Аккаунт + + + + + General + Головні + + + + + Audio / Video + + + + + System + Система + + + + Enable desktop notifications + + + + + Keep minimized on close + Згортати вікно при закриванні + + + + Download folder + + + + + Save in + Зберігти в + + + + Always Recording + + + + + Updates + + + + + Check for updates automatically every + + + + + Interval between update checks in days selector + + + + + days + + + + + Check for updates now button + + + + + Check for updates now + + + + + Password + Пароль + + + + + Enable + Увімкнути + + + + toggle enable notifications + + + + + Toggle keep minimized on close + + + + + Call Recordings + + + + + Toggle automatic updates + + + + + Jami Account + + + + + + Profile + Профіль + + + + + Identity + Особа + + + + Id + + + + + Registered name + Зареєстроване ім'я + + + + Type here to register a username + + + + + Register + Зареєструватися + + + + Change Password + + + + + Export Account + Вивантажити обліковий запис + + + + + Delete Account + + + + + Linked Devices + + + + + Link Another Device + + + + + Banned Contacts + Заблоковані контакти + + + + Format + + + + + Video device framerate selector + + + + + Preview unavailable + + + + + + Advanced Account Settings + + + + + SIP Account + Аккаунт SIP + + + + Username + Ім’я + + + + Hostname + Ім'я хоста + + + + Proxy + Проксі + + + + Audio + Звук + + + + Microphone + + + + + Audio input device selector + + + + + Output Device + Пристрій Виведення + + + + Choose the output device + + + + + Video + Відео + + + + Device + Пристрій + + + + Video device selector + + + + + A registered name should not have any spaces and must be at least three letters long + + + + + This name is already taken + + + + + + Enter an alias + + + + + Register this name + + + + + Remove Device + + + + + Enter this account's password to confirm the removal of this device + + + + + Are you sure you wish to remove this device? + + + + + Export Account Here + + + + + Select A Folder For Your Downloads + + + + + Select A Folder For Your Recordings + + + + + VideoOverlay + + + Call on Hold + Виклик на утриманні + + + + Hold / Unhold + Утримати / Заняти з утримування + + + + Chat + Чат + + + + Mute Mic + Відключити мікрофон + + + + Record call + Запис дзвінка + + + + Name label + Назва етикетки + + + + Time elapsed + Витрачено часу + + + + 00:00 + 00:00 + + + + Hangup + Відновлення виклику + + + + Mute Video + Відключити відео + + + + VideoView + + + Share entire screen + Поділитися частиною екрану + + + + Share screen area + Поділитися екраном + + + + Share file + Відправити файл + + + \ No newline at end of file diff --git a/translations/ring_client_windows_zh.ts b/translations/ring_client_windows_zh.ts new file mode 100644 index 00000000..74332296 --- /dev/null +++ b/translations/ring_client_windows_zh.ts @@ -0,0 +1,1589 @@ + + + AboutDialog + + + + About + 關於 + + + + about button + + + + + credits button + + + + + Credits + + + + + Free as in Freedom + + + + + The Microsoft Windows client for Jami. +Jami is a secured and distributed communication software. + + + + + version + 版本 + + + + Created by: + + + + + Artwork by: + + + + + Based on the SFLPhone project + + + + + AccountItemDelegate + + + Add Account + + + + + AdvancedSIPSettingsWidget + + + Form + + + + + Call Settings + + + + + Auto Answer Calls + + + + + Enable Custom Ringtone + + + + + Connectivity + + + + + STUN Address + + + + + Use STUN + 使用STUN + + + + Use UPnP + + + + + Use TURN + 使用TURN + + + + TURN Password + + + + + TURN Username + + + + + TURN Address + + + + + Media + 媒體 + + + + Enable Video + 啟用視訊 + + + + Video Codecs + + + + + Audio Codecs + + + + + Audio Files (*.wav *.ogg *.opus *.mp3 *aiff *wma) + + + + + Add a custom ringtone + + + + + AdvancedSettingsWidget + + + Form + + + + + Call Settings + + + + + Allow Calls From Untrusted Peers + + + + + Auto Answer Calls + + + + + Enable Custom Ringtone + + + + + Add a custom ringtone + + + + + Name Server + + + + + Address + 地址 + + + + OpenDHT Configuration + + + + + Enable Proxy + + + + + Bootstrap + 引導 + + + + Security + 安全 + + + + Private Key Password + + + + + User Certificate + 使用者認證 + + + + Private Key + + + + + CA Certificate + + + + + Connectivity + + + + + Use STUN + 使用STUN + + + + STUN Address + + + + + Use UPnP + + + + + Use TURN + 使用TURN + + + + TURN Password + + + + + TURN Username + + + + + TURN Address + + + + + Media + 媒體 + + + + Enable Video + 啟用視訊 + + + + Audio Codecs + + + + + Video Codecs + + + + + Audio Files (*.wav *.ogg *.opus *.mp3 *aiff *wma) + + + + + AnimatedOverlay + + + Form + + + + + BannedItemWidget + + + Form + + + + + name + + + + + id + + + + + CallWidget + + + Show conversations + + + + + Conversations + 對話 + + + + Search contact text input + + + + + Jami is free software for universal communication which respects the freedoms and privacy of its users. + + + + + + This is your ID. +Copy and share it with your friends! + + + + + + Show ring ID QR code + + + + + Share ring ID button + + + + + Double-click to copy + + + + + Error while generating QR Code + + + + + + best name + + + + + best Id + + + + + Back to homepage button + + + + + Add to contacts + 加到聯絡人 + + + + Show invites + + + + + Invites + + + + + + Find a new or existing contact + + + + + Wants to talk to you! + 想要與你談天! + + + + Answer incoming call button + + + + + Ignore incoming call button + + + + + Answer + 接通 + + + + Ignore + 忽略 + + + + Cancel outgoing call + + + + + Cancel + 取消 + + + + Start video call + + + + + Start audio call + + + + + Clear conversation + + + + + Remove contact + + + + + Block contact + + + + + Copy number + 複製號碼 + + + + Search your received invitations + + + + + Contact me on Jami + + + + + My Id is : + + + + + %1 + %1 is the contact username + + + + + %1 + %1 is the contact unique identifier + + + + + Call incoming from %1 + + + + + DeleteAccountDialog + + + Account deletion + + + + + Do you really want to delete the following account? + + + + + If this account hasn't been exported, or added to another device, it will be irrevocably lost. + + + + + Permanently delete account + + + + + Delete + 刪除 + + + + Cancel account deletion + + + + + Cancel + 取消 + + + + DeviceItemWidget + + + Form + + + + + Device Id + + + + + this device + + + + + InviteButtonsWidget + + + Accept + + + + + Refuse + 拒絕 + + + + Block + + + + + LinkDeviceDialog + + + Dialog + + + + + Enter your account password + + + + + Password + 密码 + + + + Ok + 確定 + + + + Cancel + 取消 + + + + Exporting account + + + + + Your PIN is + + + + + PIN + + + + + This pin and the account password should be entered in your device within 10 minutes. + + + + + Close + + + + + Link Another Device + + + + + Incorrect password + + + + + Something went wrong. +Please try again later. + + + + + MainWindow + + + Settings + 設定 + + + + Exit + 離開 + + + + About + 關於 + + + + Jami + + + + + NameRegistrationDialog + + + Set Registered Name + + + + + Enter your account password + + + + + Password text input + + + + + Password text entry + + + + + Password + 密码 + + + + Register + + + + + Cancel + 取消 + + + + Registering Name + + + + + Something went wrong + + + + + Close + + + + + Incorrect password + + + + + Network error + + + + + NewWizardWidget + + + Form + + + + + Welcome Label + + + + + Welcome to + + + + + Welcome Logo + + + + + Create Jami account button + + + + + Push button for Jami account creation start trigger + + + + + Create a Jami account + + + + + Link device button + + + + + Push button for device linkage start trigger + + + + + Link this device to an account + + + + + Create Jami SIP account button + + + + + Push button for Jami SIP account creation start trigger + + + + + Create a SIP account + + + + + Link this device to an existing account + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Ubuntu'; font-size:14px; color:#555555;">To link this device to another account, you first </span><span style=" font-family:'Ubuntu'; font-size:14px; font-weight:600; color:#555555;">need to obtain a PIN</span><span style=" font-family:'Ubuntu'; font-size:14px; color:#555555;"> code. To generate the PIN code:</span></p> +<ol style="margin-top: 0px; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; -qt-list-indent: 1;"><li style=" font-family:'Ubuntu'; font-size:14px; color:#555555;" style=" margin-top:12px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:14px;">Go to the </span><span style=" font-size:14px; font-weight:600;">Account management setting</span><span style=" font-size:14px;"> of a previous device</span></li> +<li style=" font-family:'Ubuntu'; font-size:14px; color:#555555;" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:14px;">Choose the </span><span style=" font-size:14px; font-weight:600;">Jami account</span><span style=" font-size:14px;"> you want to use</span></li> +<li style=" font-family:'Ubuntu'; font-size:14px; color:#555555;" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:14px;">Go to the </span><span style=" font-size:14px; font-weight:600;">Devices</span><span style=" font-size:14px;"> tab</span></li> +<li style=" font-family:'Ubuntu'; font-size:14px; color:#555555;" style=" margin-top:0px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:14px;">Select </span><span style=" font-size:14px; font-weight:600;">Add a device</span></li></ol> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Ubuntu'; font-size:14px; color:#555555;">You will get the necessary PIN to complete this form. The PIN is only valid for </span><span style=" font-family:'Ubuntu'; font-size:14px; font-weight:600; color:#555555;">10 minutes</span><span style=" font-family:'Ubuntu'; font-size:10px; color:#555555;">.</span></p></body></html> + + + + + Enter your pin: + + + + + Or import a file: + + + + + Link from exported account archive file + + + + + + + (None) + + + + + Password: + + + + + + Profile + 個人檔案 + + + + + Profile name + + + + + Account + 帳號 + + + + Register your username. +This will reserve the username so that only you can use it. +Your friends will be able to call you with your usename +instead of using your ID. + + + + + Public username checkbox + + + + + Checkbox selecting if the user wants a public username + + + + + Register public username + + + + + Public username edit + + + + + Choose your username + 選擇你的使用者名稱 + + + + Password text input + + + + + Password text entry + + + + + + Password + 密码 + + + + + Password confirmation text input + + + + + Confirm password + + + + + SIP Account + + + + + SIP Server edit + + + + + Server + + + + + SIP proxy input + + + + + SIP proxy text entry + + + + + Proxy + 代理 + + + + SIP username input + + + + + SIP Password text entry + + + + + Username + 使用者名 + + + + + SIP Password text input + + + + + Generating your Jami account… + + + + + Previous page button + + + + + push button to access previous page of wizard + + + + + Previous + + + + + Cancel account create/link + + + + + push button to cancel account creation or linking + + + + + Back + + + + + Next page Button + + + + + Push button to access next page of wizard + + + + + Next + 下一步 + + + + Open File + 開啟檔案 + + + + Jami archive files (*.gz); All files (*) + + + + + Your account needs to be migrated. Enter your password. + + + + + Migrating your Jami account... + + + + + Importing account archive... + + + + + Generating your Jami account... + + + + + Generating your SIP account... + + + + + Error creating account + + + + + PasswordDialog + + + Change Account Password + + + + + Enter Current Password + + + + + Enter New Password + + + + + Confirm New Password + + + + + Confirm + + + + + Cancel + 取消 + + + + Current Password Incorrect + + + + + PhotoBoothDialog + + + Photobooth + + + + + PhotoboothWidget + + + Form + + + + + Photobooth display + + + + + Choose File + 選擇檔案 + + + + Image Files (*.jpg *.jpeg *.png) + + + + + PrivateBridging + + + Choose File + 選擇檔案 + + + + Files (*) + 檔案(*) + + + + QObject + + + No default mail client found + + + + + + Edit Device Name + + + + + Unlink Device From Account + + + + + Save new device name + + + + + Add as contact + + + + + RingButton + + + Select folder + + + + + SettingsWidget + + + Form + + + + + Settings + 設定 + + + + Account + 帳號 + + + + + General + 通用 + + + + + Audio / Video + + + + + System + + + + + Enable desktop notifications + + + + + Keep minimized on close + + + + + Download folder + + + + + Save in + + + + + Always Recording + + + + + Updates + + + + + Check for updates automatically every + + + + + Interval between update checks in days selector + + + + + days + + + + + Check for updates now button + + + + + Check for updates now + + + + + Password + 密码 + + + + + Enable + + + + + toggle enable notifications + + + + + Toggle keep minimized on close + + + + + Call Recordings + + + + + Toggle automatic updates + + + + + Jami Account + + + + + + Profile + 個人檔案 + + + + + Identity + + + + + Id + + + + + Registered name + + + + + Type here to register a username + + + + + Register + + + + + Change Password + + + + + Export Account + + + + + + Delete Account + + + + + Linked Devices + + + + + Link Another Device + + + + + Banned Contacts + + + + + Format + + + + + Video device framerate selector + + + + + Preview unavailable + + + + + + Advanced Account Settings + + + + + SIP Account + + + + + Username + 使用者名 + + + + Hostname + 主機名稱 + + + + Proxy + 代理 + + + + Audio + 語音 + + + + Microphone + + + + + Audio input device selector + + + + + Output Device + 輸出裝置 + + + + Choose the output device + + + + + Video + 影像 + + + + Device + 裝置 + + + + Video device selector + + + + + A registered name should not have any spaces and must be at least three letters long + + + + + This name is already taken + + + + + + Enter an alias + + + + + Register this name + + + + + Remove Device + + + + + Enter this account's password to confirm the removal of this device + + + + + Are you sure you wish to remove this device? + + + + + Export Account Here + + + + + Select A Folder For Your Downloads + + + + + Select A Folder For Your Recordings + + + + + VideoOverlay + + + Call on Hold + + + + + Hold / Unhold + + + + + Chat + 聊天 + + + + Mute Mic + 麥克風靜音 + + + + Record call + + + + + Name label + + + + + Time elapsed + 經過時間 + + + + 00:00 + 00:00 + + + + Hangup + + + + + Mute Video + 視訊靜音 + + + + VideoView + + + Share entire screen + 分享整個螢幕 + + + + Share screen area + 分享部分螢幕 + + + + Share file + 分享檔案 + + + \ No newline at end of file diff --git a/translations/ring_client_windows_zh_CN.ts b/translations/ring_client_windows_zh_CN.ts new file mode 100644 index 00000000..de17cad0 --- /dev/null +++ b/translations/ring_client_windows_zh_CN.ts @@ -0,0 +1,1606 @@ + + + AboutDialog + + + + About + 关于 + + + + about button + 关于按钮 + + + + credits button + 致谢按钮 + + + + Credits + 致谢 + + + + Free as in Freedom + "Free as in Freedom" + + + + The Microsoft Windows client for Jami. +Jami is a secured and distributed communication software. + Jami 的 Microsoft Windows 客户端。 +Jami 是一款加密、分布式的通讯软件。 + + + + version + 版本 + + + + Created by: + 开发者: + + + + Artwork by: + 美工设计: + + + + Based on the SFLPhone project + 基于 SFLPhone 项目 + + + + AccountItemDelegate + + + Add Account + 添加账户 + + + + AdvancedSIPSettingsWidget + + + Form + 表单 + + + + Call Settings + 呼叫设置 + + + + Auto Answer Calls + 自动接听来电 + + + + Enable Custom Ringtone + 启用自定义铃声 + + + + Connectivity + 连接性 + + + + STUN Address + STUN地址 + + + + Use STUN + 使用STUN + + + + Use UPnP + 使用UPnP + + + + Use TURN + 使用TURN + + + + TURN Password + TURN密码 + + + + TURN Username + TURN用户名 + + + + TURN Address + TURN地址 + + + + Media + 媒体 + + + + Enable Video + 启用视频 + + + + Video Codecs + 视频编码 + + + + Audio Codecs + 音频编码 + + + + Audio Files (*.wav *.ogg *.opus *.mp3 *aiff *wma) + 音频文件(*.wav *.ogg *.opus *.mp3 *aiff *wma) + + + + Add a custom ringtone + 添加自定义铃声 + + + + AdvancedSettingsWidget + + + Form + 表单 + + + + Call Settings + 呼叫设置 + + + + Allow Calls From Untrusted Peers + 允许未被信任的用户来电 + + + + Auto Answer Calls + 自动接听来电 + + + + Enable Custom Ringtone + 启用自定义铃声 + + + + Add a custom ringtone + 添加自定义铃声 + + + + Name Server + 名称服务器 + + + + Address + 地址: + + + + OpenDHT Configuration + OpenDHT配置 + + + + Enable Proxy + 启用代理 + + + + Bootstrap + 初始服务器 + + + + Security + 安全 + + + + Private Key Password + 私钥密码 + + + + User Certificate + 用户证书 + + + + Private Key + 私钥 + + + + CA Certificate + 颁发机构证书 + + + + Connectivity + 连接性 + + + + Use STUN + 使用STUN + + + + STUN Address + STUN地址 + + + + Use UPnP + 使用UPnP + + + + Use TURN + 使用TURN + + + + TURN Password + TURN密码 + + + + TURN Username + TURN用户名 + + + + TURN Address + TURN地址 + + + + Media + 媒体 + + + + Enable Video + 启用视频 + + + + Audio Codecs + 音频编码 + + + + Video Codecs + 视频编码 + + + + Audio Files (*.wav *.ogg *.opus *.mp3 *aiff *wma) + 音频文件(*.wav *.ogg *.opus *.mp3 *aiff *wma) + + + + AnimatedOverlay + + + Form + 表单 + + + + BannedItemWidget + + + Form + 表单 + + + + name + 姓名 + + + + id + id + + + + CallWidget + + + Show conversations + 显示会话 + + + + Conversations + 会话 + + + + Search contact text input + 搜索联系人文本输入 + + + + Jami is free software for universal communication which respects the freedoms and privacy of its users. + Jami是一种自由通信软件,它尊重用户的自由和隐私。 + + + + + This is your ID. +Copy and share it with your friends! + + +这是您的ID。 +复制并发送给您的朋友! + + + + + Show ring ID QR code + 显示RingID二维码 + + + + Share ring ID button + 分享ring ID按钮 + + + + Double-click to copy + 双击复制 + + + + Error while generating QR Code + 创建二维码时产生错误 + + + + + best name + 最佳名字 + + + + best Id + 最佳Id + + + + Back to homepage button + 返回主页按钮 + + + + Add to contacts + 加入通讯录 + + + + Show invites + 显示邀请 + + + + Invites + 邀请 + + + + + Find a new or existing contact + 查找新的或现有的联系人 + + + + Wants to talk to you! + 想要与您通信! + + + + Answer incoming call button + 接听来电按钮 + + + + Ignore incoming call button + 忽略来电按钮 + + + + Answer + 应答 + + + + Ignore + 忽略 + + + + Cancel outgoing call + 取消拨出的电话 + + + + Cancel + 取消 + + + + Start video call + 发起视频通话 + + + + Start audio call + 发起语音通话 + + + + Clear conversation + 清除会话 + + + + Remove contact + 删除联系人 + + + + Block contact + 屏蔽联系人 + + + + Copy number + 复制号码 + + + + Search your received invitations + 搜索收到的邀请 + + + + Contact me on Jami + 在Jami上联系我 + + + + My Id is : + 我的ID是: + + + + %1 + %1 is the contact username + %1 + + + + %1 + %1 is the contact unique identifier + %1 + + + + Call incoming from %1 + 来电:%1 + + + + DeleteAccountDialog + + + Account deletion + 删除账户 + + + + Do you really want to delete the following account? + 确定删除以下账户吗? + + + + If this account hasn't been exported, or added to another device, it will be irrevocably lost. + 如果此账户尚未导出或添加到其他设备,它将不可挽回地丢失。 + + + + Permanently delete account + 永久删除账户 + + + + Delete + 删除 + + + + Cancel account deletion + 取消账户删除 + + + + Cancel + 取消 + + + + DeviceItemWidget + + + Form + 表单 + + + + Device Id + 设备ID + + + + this device + 该设备 + + + + InviteButtonsWidget + + + Accept + 接听 + + + + Refuse + 拒接 + + + + Block + 屏蔽 + + + + LinkDeviceDialog + + + Dialog + 对话框 + + + + Enter your account password + 输入您的账户密码 + + + + Password + 密码 + + + + Ok + 确定 + + + + Cancel + 取消 + + + + Exporting account + 正导出账户 + + + + Your PIN is + 您的PIN码是 + + + + PIN + PIN + + + + This pin and the account password should be entered in your device within 10 minutes. + 您需在 10 分钟内在您的设备上输入此 PIN 码和账户密码。 + + + + Close + 关闭 + + + + Link Another Device + 连结其他设备 + + + + Incorrect password + 密码错误 + + + + Something went wrong. +Please try again later. + 有些不对劲。 +请稍后再试 + + + + MainWindow + + + Settings + 设置 + + + + Exit + 退出 + + + + About + 关于 + + + + Jami + Jami + + + + NameRegistrationDialog + + + Set Registered Name + 设置注册名称 + + + + Enter your account password + 输入您的账户密码 + + + + Password text input + 密码文本输入 + + + + Password text entry + 密码文本条目 + + + + Password + 密码 + + + + Register + 注册 + + + + Cancel + 取消 + + + + Registering Name + 正在注册名称 + + + + Something went wrong + 有些不对劲 + + + + Close + 关闭 + + + + Incorrect password + 密码错误 + + + + Network error + 网络错误 + + + + NewWizardWidget + + + Form + 表单 + + + + Welcome Label + 欢迎标签 + + + + Welcome to + 欢迎来到 + + + + Welcome Logo + 欢迎图标 + + + + Create Jami account button + 创建Jami账户按钮 + + + + Push button for Jami account creation start trigger + 按下Jami账户创建按钮开始触发 + + + + Create a Jami account + 创建一个Jami账户 + + + + Link device button + 连结设备按钮 + + + + Push button for device linkage start trigger + 按下设备连结按钮开始触发 + + + + Link this device to an account + 将此设备与一个账户进行连接 + + + + Create Jami SIP account button + 创建 Jami SIP 账户按钮 + + + + Push button for Jami SIP account creation start trigger + 按下 Jami SIP 账户创建按钮开始触发 + + + + Create a SIP account + 创建 SIP 账户 + + + + Link this device to an existing account + 将此设备与已有账户进行连接 + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Ubuntu'; font-size:14px; color:#555555;">To link this device to another account, you first </span><span style=" font-family:'Ubuntu'; font-size:14px; font-weight:600; color:#555555;">need to obtain a PIN</span><span style=" font-family:'Ubuntu'; font-size:14px; color:#555555;"> code. To generate the PIN code:</span></p> +<ol style="margin-top: 0px; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; -qt-list-indent: 1;"><li style=" font-family:'Ubuntu'; font-size:14px; color:#555555;" style=" margin-top:12px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:14px;">Go to the </span><span style=" font-size:14px; font-weight:600;">Account management setting</span><span style=" font-size:14px;"> of a previous device</span></li> +<li style=" font-family:'Ubuntu'; font-size:14px; color:#555555;" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:14px;">Choose the </span><span style=" font-size:14px; font-weight:600;">Jami account</span><span style=" font-size:14px;"> you want to use</span></li> +<li style=" font-family:'Ubuntu'; font-size:14px; color:#555555;" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:14px;">Go to the </span><span style=" font-size:14px; font-weight:600;">Devices</span><span style=" font-size:14px;"> tab</span></li> +<li style=" font-family:'Ubuntu'; font-size:14px; color:#555555;" style=" margin-top:0px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:14px;">Select </span><span style=" font-size:14px; font-weight:600;">Add a device</span></li></ol> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Ubuntu'; font-size:14px; color:#555555;">You will get the necessary PIN to complete this form. The PIN is only valid for </span><span style=" font-family:'Ubuntu'; font-size:14px; font-weight:600; color:#555555;">10 minutes</span><span style=" font-family:'Ubuntu'; font-size:10px; color:#555555;">.</span></p></body></html> + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Ubuntu'; font-size:14px; color:#555555;">要将此设备关联到账户,首先您 </span><span style=" font-family:'Ubuntu'; font-size:14px; font-weight:600; color:#555555;"> 需要获取 PIN</span><span style=" font-family:'Ubuntu'; font-size:14px; color:#555555;"> 码。 要生成 PIN 码:</span></p> +<ol style="margin-top: 0px; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; -qt-list-indent: 1;"><li style=" font-family:'Ubuntu'; font-size:14px; color:#555555;" style=" margin-top:12px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:14px;">需前往 </span><span style=" font-size:14px; font-weight:600;">先前设备的</span><span style=" font-size:14px;"> 账户管理设置中</span></li> +<li style=" font-family:'Ubuntu'; font-size:14px; color:#555555;" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:14px;">选择 </span><span style=" font-size:14px; font-weight:600;">您要使用的</span><span style=" font-size:14px;"> Jami 账户</span></li> +<li style=" font-family:'Ubuntu'; font-size:14px; color:#555555;" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:14px;">到 </span><span style=" font-size:14px; font-weight:600;">设备</span><span style=" font-size:14px;"> 选项卡下</span></li> +<li style=" font-family:'Ubuntu'; font-size:14px; color:#555555;" style=" margin-top:0px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:14px;">选择 </span><span style=" font-size:14px; font-weight:600;">添加设备</span></li></ol> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Ubuntu'; font-size:14px; color:#555555;">您会得到填写本栏所需的 PIN 码。PIN 码有效期为 </span><span style=" font-family:'Ubuntu'; font-size:14px; font-weight:600; color:#555555;">10 分钟</span><span style=" font-family:'Ubuntu'; font-size:10px; color:#555555;">。</span></p></body></html> + + + + Enter your pin: + 输入您的PIN: + + + + Or import a file: + 或导入一个文件: + + + + Link from exported account archive file + 用导出账户的存档文件进行设备连结 + + + + + + (None) + (无) + + + + Password: + 密码: + + + + + Profile + 账户资料 + + + + + Profile name + 个人资料名称 + + + + Account + 账户 + + + + Register your username. +This will reserve the username so that only you can use it. +Your friends will be able to call you with your usename +instead of using your ID. + 用你的用户名注册 +这将保留用户名,以便只有您可以使用它 +您的朋友可以使用您的用户名给您打电话 +而非用你的ID + + + + Public username checkbox + 公开用户名的复选框 + + + + Checkbox selecting if the user wants a public username + 如果用户想要公开的用户名就勾选这个复选框 + + + + Register public username + 注册公共用户名 + + + + Public username edit + 编辑公开用户名 + + + + Choose your username + 设置您的用户名 + + + + Password text input + 密码文本输入 + + + + Password text entry + 密码文本条目 + + + + + Password + 密码 + + + + + Password confirmation text input + 确认密码文本输入 + + + + Confirm password + 确认密码 + + + + SIP Account + SIP 账户 + + + + SIP Server edit + 编辑SIP服务器 + + + + Server + 服务器 + + + + SIP proxy input + 输入SIP代理 + + + + SIP proxy text entry + SIP代理文本条目 + + + + Proxy + 代理 + + + + SIP username input + SIP用户名输入 + + + + SIP Password text entry + SIP密码文本条目 + + + + Username + 用户名 + + + + + SIP Password text input + SIP密码文本输入 + + + + Generating your Jami account… + 正在生成您的Jami账户… + + + + Previous page button + 上一页按钮 + + + + push button to access previous page of wizard + 按按钮访问向导的上一页 + + + + Previous + 上一步 + + + + Cancel account create/link + 取消账户创建/连结 + + + + push button to cancel account creation or linking + 按按钮取消账户创建或连结 + + + + Back + 上一步 + + + + Next page Button + 下一页按钮 + + + + Push button to access next page of wizard + 按按钮来访问向导的下一页 + + + + Next + 下一步 + + + + Open File + 打开文件 + + + + Jami archive files (*.gz); All files (*) + Jami档案文件 (*.gz); 所有文件 (*) + + + + Your account needs to be migrated. Enter your password. + 您的Ring账户可以被更新。\n请输入您的密码。 + + + + Migrating your Jami account... + 正在迁移您的Jami账户… + + + + Importing account archive... + 正导入账户存档... + + + + Generating your Jami account... + 正在生成您的Jami账户… + + + + Generating your SIP account... + 正在生成您的SIP账户… + + + + Error creating account + 创建账户时发生错误 + + + + PasswordDialog + + + Change Account Password + 更改账户密码 + + + + Enter Current Password + 输入当前密码 + + + + Enter New Password + 输入新密码 + + + + Confirm New Password + 确认新密码 + + + + Confirm + 确认 + + + + Cancel + 取消 + + + + Current Password Incorrect + 当前密码错误 + + + + PhotoBoothDialog + + + Photobooth + Photobooth + + + + PhotoboothWidget + + + Form + 表单 + + + + Photobooth display + 照片展台展示 + + + + Choose File + 选择文件 + + + + Image Files (*.jpg *.jpeg *.png) + 图像文件(* .jpg * .jpeg * .png) + + + + PrivateBridging + + + Choose File + 选择文件 + + + + Files (*) + 文件 (*) + + + + QObject + + + No default mail client found + 未找到默认邮件客户端 + + + + + Edit Device Name + 编辑设备名 + + + + Unlink Device From Account + 取消设备与账户的链接 + + + + Save new device name + 保存新设备名称 + + + + Add as contact + 添加为联系人 + + + + RingButton + + + Select folder + 选择文件夹 + + + + SettingsWidget + + + Form + 表单 + + + + Settings + 设置 + + + + Account + 账户 + + + + + General + 通用 + + + + + Audio / Video + 音频/视频 + + + + System + 系统 + + + + Enable desktop notifications + 启用桌面通知 + + + + Keep minimized on close + 退出时保持窗口最小化 + + + + Download folder + 下载文件夹 + + + + Save in + 保存至 + + + + Always Recording + 总是录音 + + + + Updates + 更新 + + + + Check for updates automatically every + 自动检查更新:每 + + + + Interval between update checks in days selector + 每隔几天检查更新 + + + + days + + + + + Check for updates now button + 现在检查更新按钮 + + + + Check for updates now + 立即检查更新 + + + + Password + 密码 + + + + + Enable + 启用 + + + + toggle enable notifications + 是否启用通知 + + + + Toggle keep minimized on close + 是否在关闭时保持最小化 + + + + Call Recordings + 通话录音 + + + + Toggle automatic updates + 是否自动更新应用 + + + + Jami Account + Jami账户 + + + + + Profile + 资料 + + + + + Identity + 身份 + + + + Id + ID + + + + Registered name + 已注册名称 + + + + Type here to register a username + 在此处输入注册用户名 + + + + Register + 注册 + + + + Change Password + 更改用户名 + + + + Export Account + 导出账户 + + + + + Delete Account + 删除账户 + + + + Linked Devices + 连结的设备 + + + + Link Another Device + 连结其他设备 + + + + Banned Contacts + 已屏蔽的联系人 + + + + Format + 格式 + + + + Video device framerate selector + 选择视频设备帧率 + + + + Preview unavailable + 预览不可用 + + + + + Advanced Account Settings + 高级账户设置 + + + + SIP Account + SIP 账户 + + + + Username + 用户名 + + + + Hostname + 主机名 + + + + Proxy + 代理 + + + + Audio + 音频 + + + + Microphone + 麦克风 + + + + Audio input device selector + 选择音频输入设备 + + + + Output Device + 输出设备 + + + + Choose the output device + 选择输出设备 + + + + Video + 视频 + + + + Device + 设备 + + + + Video device selector + 选择视频设备 + + + + A registered name should not have any spaces and must be at least three letters long + 注册名称不得有空格,并且必须至少包含三个字母 + + + + This name is already taken + 这个名字已被占用 + + + + + Enter an alias + 输入别名 + + + + Register this name + 注册这个名字 + + + + Remove Device + 删除设备 + + + + Enter this account's password to confirm the removal of this device + 输入此账户的密码,以确认删除该设备 + + + + Are you sure you wish to remove this device? + 您确定要删除此设备吗? + + + + Export Account Here + 此处导出账户 + + + + Select A Folder For Your Downloads + 为您下载的文件选择一个文件夹 + + + + Select A Folder For Your Recordings + 为你的录音挑选一个文件夹 + + + + VideoOverlay + + + Call on Hold + 通话等待中 + + + + Hold / Unhold + 等待/取消等待 + + + + Chat + 聊天 + + + + Mute Mic + 将麦克风静音 + + + + Record call + 录制通话 + + + + Name label + 名称标签 + + + + Time elapsed + 用时 + + + + 00:00 + 00:00 + + + + Hangup + 挂断 + + + + Mute Video + 关闭视频 + + + + VideoView + + + Share entire screen + 共享整个屏幕 + + + + Share screen area + 共享屏幕区域 + + + + Share file + 共享文件 + + + \ No newline at end of file diff --git a/translations/ring_client_windows_zh_TW.ts b/translations/ring_client_windows_zh_TW.ts new file mode 100644 index 00000000..bc7cd8e1 --- /dev/null +++ b/translations/ring_client_windows_zh_TW.ts @@ -0,0 +1,1606 @@ + + + AboutDialog + + + + About + 關於 + + + + about button + 關於按鈕 + + + + credits button + 感謝按鈕 + + + + Credits + 榮譽 + + + + Free as in Freedom + Free as in Freedom + + + + The Microsoft Windows client for Jami. +Jami is a secured and distributed communication software. + Jami 的 Microsoft Windows 客戶端。 +Jami 是一個安全且分散式的通訊軟體。 + + + + version + 版本 + + + + Created by: + 建立由: + + + + Artwork by: + 美術由: + + + + Based on the SFLPhone project + 基於 SFLPhone 專案 + + + + AccountItemDelegate + + + Add Account + 新增帳號 + + + + AdvancedSIPSettingsWidget + + + Form + 表單 + + + + Call Settings + 通話設定 + + + + Auto Answer Calls + 自動回應通話 + + + + Enable Custom Ringtone + 啟用自訂鈴聲 + + + + Connectivity + 連線 + + + + STUN Address + STUN 地址 + + + + Use STUN + 使用 STUN + + + + Use UPnP + 使用 UPnP + + + + Use TURN + 使用 TURN + + + + TURN Password + TURN 密碼 + + + + TURN Username + TURN 使用者名稱 + + + + TURN Address + TURN 地址 + + + + Media + 媒體 + + + + Enable Video + 啟用視訊 + + + + Video Codecs + 視訊編解碼器 + + + + Audio Codecs + 音訊編解碼器 + + + + Audio Files (*.wav *.ogg *.opus *.mp3 *aiff *wma) + 音訊檔 (*.wav *.ogg *.opus *.mp3 *aiff *wma) + + + + Add a custom ringtone + 新增自訂鈴聲 + + + + AdvancedSettingsWidget + + + Form + 表單 + + + + Call Settings + 通話設定 + + + + Allow Calls From Untrusted Peers + 允許來自未受信任使用者的通話 + + + + Auto Answer Calls + 自動回應通話 + + + + Enable Custom Ringtone + 啟用自訂鈴聲 + + + + Add a custom ringtone + 新增自訂鈴聲 + + + + Name Server + 名稱伺服器 + + + + Address + 地址 + + + + OpenDHT Configuration + OpenDHT 設定 + + + + Enable Proxy + 啟用代理伺服器 + + + + Bootstrap + Bootstrap + + + + Security + 安全性 + + + + Private Key Password + 私密金鑰密碼 + + + + User Certificate + 使用者憑證 + + + + Private Key + 私鑰 + + + + CA Certificate + CA 憑證 + + + + Connectivity + 連線 + + + + Use STUN + 使用 STUN + + + + STUN Address + STUN 地址 + + + + Use UPnP + 使用 UPnP + + + + Use TURN + 使用 TURN + + + + TURN Password + TURN 密碼 + + + + TURN Username + TURN 使用者名稱 + + + + TURN Address + TURN 地址 + + + + Media + 媒體 + + + + Enable Video + 啟用視訊 + + + + Audio Codecs + 音訊編解碼器 + + + + Video Codecs + 視訊編解碼器 + + + + Audio Files (*.wav *.ogg *.opus *.mp3 *aiff *wma) + 音訊檔 (*.wav *.ogg *.opus *.mp3 *aiff *wma) + + + + AnimatedOverlay + + + Form + 表單 + + + + BannedItemWidget + + + Form + 表單 + + + + name + 名稱 + + + + id + id + + + + CallWidget + + + Show conversations + 顯示對話 + + + + Conversations + 對話 + + + + Search contact text input + 搜尋聯絡人文字輸入 + + + + Jami is free software for universal communication which respects the freedoms and privacy of its users. + Jami 是一套通用通訊的自由軟體,其尊重使用者的自由與隱私。 + + + + + This is your ID. +Copy and share it with your friends! + + + 這是您的 ID。 +複製並分享它給您的朋友! + + + + + Show ring ID QR code + 顯示 Ring ID 二維條碼 + + + + Share ring ID button + 分享 Ring ID 按鈕 + + + + Double-click to copy + 雙擊以複製 + + + + Error while generating QR Code + 產生 QR Code 時發生錯誤 + + + + + best name + 最佳名稱 + + + + best Id + 最佳 ID + + + + Back to homepage button + 回到首頁按鈕 + + + + Add to contacts + 加到聯絡人 + + + + Show invites + 顯示邀請 + + + + Invites + 邀請 + + + + + Find a new or existing contact + 尋找新的或既有的聯絡人 + + + + Wants to talk to you! + 想要與您說說話! + + + + Answer incoming call button + 答覆來電按鈕 + + + + Ignore incoming call button + 忽略來電按鈕 + + + + Answer + 回覆 + + + + Ignore + 忽略 + + + + Cancel outgoing call + 取消去電 + + + + Cancel + 取消 + + + + Start video call + 開始視訊通話 + + + + Start audio call + 開始音訊通話 + + + + Clear conversation + 清除對話 + + + + Remove contact + 移除聯絡人 + + + + Block contact + 阻擋連絡人 + + + + Copy number + 複製號碼 + + + + Search your received invitations + 搜尋您收到的邀請 + + + + Contact me on Jami + 在 Jami 上聯絡我 + + + + My Id is : + 我的 Id 是: + + + + %1 + %1 is the contact username + %1 + + + + %1 + %1 is the contact unique identifier + %1 + + + + Call incoming from %1 + 從 %1 的來電 + + + + DeleteAccountDialog + + + Account deletion + 帳號刪除 + + + + Do you really want to delete the following account? + 您真的想要刪除以下的帳號嗎? + + + + If this account hasn't been exported, or added to another device, it will be irrevocably lost. + 若此帳號尚未匯出,或是新增到其他裝置,它將會不可逆地遺失。 + + + + Permanently delete account + 永久刪除帳號 + + + + Delete + 刪除 + + + + Cancel account deletion + 取消帳號刪除 + + + + Cancel + 取消 + + + + DeviceItemWidget + + + Form + 表單 + + + + Device Id + 裝置 Id + + + + this device + 此裝置 + + + + InviteButtonsWidget + + + Accept + 接聽 + + + + Refuse + 拒絕 + + + + Block + 阻擋 + + + + LinkDeviceDialog + + + Dialog + 對話框 + + + + Enter your account password + 輸入您的帳號密碼 + + + + Password + 密碼 + + + + Ok + 確定 + + + + Cancel + 取消 + + + + Exporting account + 正在匯出帳號 + + + + Your PIN is + 您的 PIN 碼為 + + + + PIN + PIN 碼 + + + + This pin and the account password should be entered in your device within 10 minutes. + 這個 PIN 碼與帳號密碼應該要在 10 分鐘之內在您的裝置上輸入。 + + + + Close + 關閉 + + + + Link Another Device + 聯結其他裝置 + + + + Incorrect password + 不正確的密碼 + + + + Something went wrong. +Please try again later. + 有東西出問題了。 +請再試一次。 + + + + MainWindow + + + Settings + 設定 + + + + Exit + 離開 + + + + About + 關於 + + + + Jami + Jami + + + + NameRegistrationDialog + + + Set Registered Name + 設定已註冊的名稱 + + + + Enter your account password + 輸入您的帳號密碼 + + + + Password text input + 密碼文字輸入 + + + + Password text entry + 密碼文字項目 + + + + Password + 密碼 + + + + Register + 註冊 + + + + Cancel + 取消 + + + + Registering Name + 註冊名稱 + + + + Something went wrong + 出了點問題 + + + + Close + 關閉 + + + + Incorrect password + 不正確的密碼 + + + + Network error + 網路錯誤 + + + + NewWizardWidget + + + Form + 表單 + + + + Welcome Label + 歡迎標籤 + + + + Welcome to + 歡迎來到 + + + + Welcome Logo + 歡迎圖示 + + + + Create Jami account button + 建立 Jami 帳號按鈕 + + + + Push button for Jami account creation start trigger + Jami 帳號建立開始觸發請按下按鈕 + + + + Create a Jami account + 建立 Jami 帳號 + + + + Link device button + 連結裝置按鈕 + + + + Push button for device linkage start trigger + 裝置連結開始觸發請按下按鈕 + + + + Link this device to an account + 連結這個裝置到一個帳號 + + + + Create Jami SIP account button + 建立 Jami SIP 帳號按鈕 + + + + Push button for Jami SIP account creation start trigger + 按下按鈕以啟動 Jami SIP 帳號建立程序 + + + + Create a SIP account + 建立 SIP 帳號 + + + + Link this device to an existing account + 連結此裝置到既有的帳號 + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Ubuntu'; font-size:14px; color:#555555;">To link this device to another account, you first </span><span style=" font-family:'Ubuntu'; font-size:14px; font-weight:600; color:#555555;">need to obtain a PIN</span><span style=" font-family:'Ubuntu'; font-size:14px; color:#555555;"> code. To generate the PIN code:</span></p> +<ol style="margin-top: 0px; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; -qt-list-indent: 1;"><li style=" font-family:'Ubuntu'; font-size:14px; color:#555555;" style=" margin-top:12px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:14px;">Go to the </span><span style=" font-size:14px; font-weight:600;">Account management setting</span><span style=" font-size:14px;"> of a previous device</span></li> +<li style=" font-family:'Ubuntu'; font-size:14px; color:#555555;" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:14px;">Choose the </span><span style=" font-size:14px; font-weight:600;">Jami account</span><span style=" font-size:14px;"> you want to use</span></li> +<li style=" font-family:'Ubuntu'; font-size:14px; color:#555555;" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:14px;">Go to the </span><span style=" font-size:14px; font-weight:600;">Devices</span><span style=" font-size:14px;"> tab</span></li> +<li style=" font-family:'Ubuntu'; font-size:14px; color:#555555;" style=" margin-top:0px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:14px;">Select </span><span style=" font-size:14px; font-weight:600;">Add a device</span></li></ol> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Ubuntu'; font-size:14px; color:#555555;">You will get the necessary PIN to complete this form. The PIN is only valid for </span><span style=" font-family:'Ubuntu'; font-size:14px; font-weight:600; color:#555555;">10 minutes</span><span style=" font-family:'Ubuntu'; font-size:10px; color:#555555;">.</span></p></body></html> + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Ubuntu'; font-size:14px; color:#555555;">要連結此裝置到其他帳號,您必須先</span><span style=" font-family:'Ubuntu'; font-size:14px; font-weight:600; color:#555555;">取得 PIN</span><span style=" font-family:'Ubuntu'; font-size:14px; color:#555555;">碼。要生成 PIN 碼:</span></p> +<ol style="margin-top: 0px; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; -qt-list-indent: 1;"><li style=" font-family:'Ubuntu'; font-size:14px; color:#555555;" style=" margin-top:12px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:14px;">請到</span><span style=" font-size:14px; font-weight:600;">帳號管理設定</span><span style=" font-size:14px;"> 在前一個裝置上</span></li> +<li style=" font-family:'Ubuntu'; font-size:14px; color:#555555;" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:14px;">選擇</span><span style=" font-size:14px; font-weight:600;">Jami 帳號</span><span style=" font-size:14px;">,當然是您想要用的</span></li> +<li style=" font-family:'Ubuntu'; font-size:14px; color:#555555;" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:14px;">到</span><span style=" font-size:14px; font-weight:600;">裝置</span><span style=" font-size:14px;"> 分頁</span></li> +<li style=" font-family:'Ubuntu'; font-size:14px; color:#555555;" style=" margin-top:0px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:14px;">選取</span><span style=" font-size:14px; font-weight:600;">新增裝置</span></li></ol> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Ubuntu'; font-size:14px; color:#555555;">您將會取得所需的 PIN 碼來完成此表單。PIN 只在</span><span style=" font-family:'Ubuntu'; font-size:14px; font-weight:600; color:#555555;">10 分鐘</span><span style=" font-family:'Ubuntu'; font-size:10px; color:#555555;">內有效。</span></p></body></html> + + + + Enter your pin: + 輸入您的 PIN 碼: + + + + Or import a file: + 或是匯入檔案: + + + + Link from exported account archive file + 從已匯出的帳號封存檔連結 + + + + + + (None) + (無) + + + + Password: + 密碼: + + + + + Profile + 介紹 + + + + + Profile name + 個人檔案名稱 + + + + Account + 帳號 + + + + Register your username. +This will reserve the username so that only you can use it. +Your friends will be able to call you with your usename +instead of using your ID. + 註冊您的使用者名稱。 +這將會保留使用者名稱,只有您可以使用它。 +您的朋友將可以使用您的使用者名稱來與您通話, +而不用使用您的 ID。 + + + + Public username checkbox + 公開使用者名稱勾選框 + + + + Checkbox selecting if the user wants a public username + 若使用者想要一個公開的使用者名稱就在勾選框打勾 + + + + Register public username + 註冊公開使用者名稱 + + + + Public username edit + 公開使用者名稱編輯 + + + + Choose your username + 選擇您的使用者名稱 + + + + Password text input + 密碼文字輸入 + + + + Password text entry + 密碼文字項目 + + + + + Password + 密碼 + + + + + Password confirmation text input + 確認密碼文字輸入 + + + + Confirm password + 確認密碼 + + + + SIP Account + SIP 帳號 + + + + SIP Server edit + SIP 伺服器編輯 + + + + Server + 伺服器 + + + + SIP proxy input + SIP 代理伺服器輸入 + + + + SIP proxy text entry + SIP 代理伺服器文字項目 + + + + Proxy + 代理服務器 + + + + SIP username input + SIP 使用者名稱輸入 + + + + SIP Password text entry + SIP 密碼文字項目 + + + + Username + 使用者名稱 + + + + + SIP Password text input + SIP 密碼文字輸入 + + + + Generating your Jami account… + 正在生成您的 Jami 帳號…… + + + + Previous page button + 先前頁面按鈕 + + + + push button to access previous page of wizard + 存取前一頁精靈請按下按鈕 + + + + Previous + 前一個 + + + + Cancel account create/link + 取消帳號建立/連結 + + + + push button to cancel account creation or linking + 按下按鈕以取消帳號建立或連結 + + + + Back + 前一個 + + + + Next page Button + 下一頁按鈕 + + + + Push button to access next page of wizard + 存取下一頁精靈請按下按鈕 + + + + Next + 下一個 + + + + Open File + 開啟檔案 + + + + Jami archive files (*.gz); All files (*) + Jami 封存檔 (*.gz); 所有檔案 (*) + + + + Your account needs to be migrated. Enter your password. + 您的帳號需要遷移。輸入您的密碼。 + + + + Migrating your Jami account... + 正在遷移您的 Jami 帳號…… + + + + Importing account archive... + 正在匯入帳號封存檔…… + + + + Generating your Jami account... + 正在生成您的 Jami 帳號…… + + + + Generating your SIP account... + 正在生成您的 SIP 帳號…… + + + + Error creating account + 無法建立帳號 + + + + PasswordDialog + + + Change Account Password + 變更帳號密碼 + + + + Enter Current Password + 輸入目前的密碼 + + + + Enter New Password + 輸入新密碼 + + + + Confirm New Password + 確認新密碼 + + + + Confirm + 確認 + + + + Cancel + 取消 + + + + Current Password Incorrect + 目前的密碼不正確 + + + + PhotoBoothDialog + + + Photobooth + 照片展台 + + + + PhotoboothWidget + + + Form + 表單 + + + + Photobooth display + 大頭貼相機顯示 + + + + Choose File + 選擇檔案 + + + + Image Files (*.jpg *.jpeg *.png) + 圖片檔 (*.jpg *.jpeg *.png) + + + + PrivateBridging + + + Choose File + 選擇檔案 + + + + Files (*) + 檔案 (*) + + + + QObject + + + No default mail client found + 找不到預設的電子郵件客戶端 + + + + + Edit Device Name + 編輯裝置名稱 + + + + Unlink Device From Account + 從帳號取消連結裝置 + + + + Save new device name + 儲存新裝置名稱 + + + + Add as contact + 新增為聯絡人 + + + + RingButton + + + Select folder + 選擇資料夾 + + + + SettingsWidget + + + Form + 表單 + + + + Settings + 設定 + + + + Account + 帳號 + + + + + General + 一般 + + + + + Audio / Video + 音訊/視訊 + + + + System + 系統 + + + + Enable desktop notifications + 啟用桌面通知 + + + + Keep minimized on close + 在關閉時保持最小化 + + + + Download folder + 下載資料夾 + + + + Save in + 儲存在 + + + + Always Recording + 總是錄製 + + + + Updates + 更新 + + + + Check for updates automatically every + 自動檢查更新每 + + + + Interval between update checks in days selector + 檢查更新間隔(以天計)選擇器 + + + + days + + + + + Check for updates now button + 立刻檢查更新按鈕 + + + + Check for updates now + 現在檢查更新 + + + + Password + 密碼 + + + + + Enable + 啟用 + + + + toggle enable notifications + 啟用通知開關 + + + + Toggle keep minimized on close + 切換時保持最小化開關 + + + + Call Recordings + 通話紀錄 + + + + Toggle automatic updates + 自動更新開關 + + + + Jami Account + Jami 帳號 + + + + + Profile + 介紹 + + + + + Identity + 身份 + + + + Id + Id + + + + Registered name + 已註冊的名稱 + + + + Type here to register a username + 在此輸入以註冊使用者名稱 + + + + Register + 註冊 + + + + Change Password + 變更密碼 + + + + Export Account + 匯出帳號 + + + + + Delete Account + 刪除帳號 + + + + Linked Devices + 已連結的裝置 + + + + Link Another Device + 聯結其他裝置 + + + + Banned Contacts + 黑名單聯絡人 + + + + Format + 格式 + + + + Video device framerate selector + 視訊裝置幀率選擇器 + + + + Preview unavailable + 預覽不可用 + + + + + Advanced Account Settings + 進階帳號設定 + + + + SIP Account + SIP 帳號 + + + + Username + 使用者名稱 + + + + Hostname + 主機名稱 + + + + Proxy + 代理服務器 + + + + Audio + 音訊 + + + + Microphone + 麥克風 + + + + Audio input device selector + 音訊輸入裝置選擇器 + + + + Output Device + 輸出裝置 + + + + Choose the output device + 選擇輸出裝置 + + + + Video + 視訊 + + + + Device + 裝置 + + + + Video device selector + 視訊裝置選擇器 + + + + A registered name should not have any spaces and must be at least three letters long + 註冊的使用者名稱不應該有任何空格,且必須至少有三個字母 + + + + This name is already taken + 這個名字已經有人用了 + + + + + Enter an alias + 輸入別名 + + + + Register this name + 註冊這個名字 + + + + Remove Device + 移除裝置 + + + + Enter this account's password to confirm the removal of this device + 輸入這個帳號的密碼以確認移除此裝置 + + + + Are you sure you wish to remove this device? + 您確定您想要移除此裝置嗎? + + + + Export Account Here + 在此匯出帳號 + + + + Select A Folder For Your Downloads + 選取您的下載資料夾 + + + + Select A Folder For Your Recordings + 選取您的錄音資料夾 + + + + VideoOverlay + + + Call on Hold + 保留中的通話 + + + + Hold / Unhold + 保留/繼續通話 + + + + Chat + 聊天 + + + + Mute Mic + 麥克風靜音 + + + + Record call + 記錄通話 + + + + Name label + 名稱標籤 + + + + Time elapsed + 時間流逝 + + + + 00:00 + 00:00 + + + + Hangup + 掛斷 + + + + Mute Video + 視訊靜音 + + + + VideoView + + + Share entire screen + 分享整個螢幕 + + + + Share screen area + 分享螢幕區域 + + + + Share file + 分享檔案 + + + \ No newline at end of file diff --git a/update-translations.py b/update-translations.py new file mode 100755 index 00000000..0cbc9d22 --- /dev/null +++ b/update-translations.py @@ -0,0 +1,62 @@ +#!/usr/bin/python + +## +## Copyright (C) 2016-2017 Savoir-faire Linux Inc. +## +## Author: Edric Milaret +## Author: Guillaume Roguez +## +## 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, write to the Free Software +## Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +## + +import os +import shutil + +print("== Updating from sources") +if os.system("lupdate jami-qt.pro -no-obsolete"): + print("trying with 'lupdate-qt5'") + if os.system("lupdate-qt5 jami-qt.pro -no-obsolete"): + raise RuntimeError("unable to find any suitable lupdate Qt tool on this system. Stopping") + +print("== Pushing sources") +os.system("tx push -s") + +print("== Pulling translations") +os.system("tx pull -af --minimum-perc=1") + +print("Updating .pro file") + +translationFiles = [] + +for filename in os.listdir('./translations'): + translationFiles.append("translations/{0}".format(filename)) + +proFile = "jami-qt.pro" +shutil.move(proFile, proFile + "~") + +destination = open(proFile, "w") +source = open(proFile + "~", "r") +for line in source: + if not ".ts" in line: + destination.write(line) + if "TRANSLATIONS = " in line: + for filename in translationFiles: + destination.write(" {0} \\\n".format(filename)) + +source.close() +destination.close() +os.remove(proFile + "~") + +print("== All done you can commit now")