- Add auto download mode and use 10Mb as default.

- Fix notification thumbnail display on receiving file
- Fix empty name on uploading files
- Fix readonly chat room when someone is leaving
- Remove downloaded file on ephemerals
- Reduce iteration on background
This commit is contained in:
Julien Wadel 2022-03-18 13:00:14 +01:00
parent f2ec342cca
commit f4f92094b3
26 changed files with 196 additions and 36 deletions

View file

@ -1,5 +1,8 @@
<?xml version="1.0" encoding="UTF-8"?>
<config xmlns="http://www.linphone.org/xsds/lpconfig.xsd" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.linphone.org/xsds/lpconfig.xsd lpconfig.xsd">
<section name="app">
<entry name="auto_download_incoming_files_max_size" overwrite="true">10000000</entry>
</section>
<section name="proxy_default_values">
<entry name="avpf" overwrite="true">1</entry>
<entry name="dial_escape_plus" overwrite="true">0</entry>

View file

@ -1,5 +1,8 @@
<?xml version="1.0" encoding="UTF-8"?>
<config xmlns="http://www.linphone.org/xsds/lpconfig.xsd" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.linphone.org/xsds/lpconfig.xsd lpconfig.xsd">
<section name="app">
<entry name="auto_download_incoming_files_max_size" overwrite="true">10000000</entry>
</section>
<section name="proxy_default_values">
<entry name="avpf" overwrite="true">1</entry>
<entry name="dial_escape_plus" overwrite="true">0</entry>

View file

@ -1,5 +1,8 @@
<?xml version="1.0" encoding="UTF-8"?>
<config xmlns="http://www.linphone.org/xsds/lpconfig.xsd" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.linphone.org/xsds/lpconfig.xsd lpconfig.xsd">
<section name="app">
<entry name="auto_download_incoming_files_max_size" overwrite="true">10000000</entry>
</section>
<section name="proxy_default_values">
<entry name="avpf" overwrite="true">0</entry>
<entry name="dial_escape_plus" overwrite="true">0</entry>

View file

@ -1970,6 +1970,21 @@ Click here: &lt;a href=&quot;%1&quot;&gt;%1&lt;/a&gt;
<extracomment>&apos;Enable notifications&apos;: settings label for enabling notifications.</extracomment>
<translation>Enable notifications</translation>
</message>
<message>
<source>AutoDownload</source>
<extracomment>&apos;Auto download&apos; : Label for a slider about auto download mode</extracomment>
<translation>Auto download</translation>
</message>
<message>
<source>autoDownloadNever</source>
<extracomment>&apos;Never&apos; : auto download mode description for deactivated feature.</extracomment>
<translation>Never</translation>
</message>
<message>
<source>autoDownloadAlways</source>
<extracomment>&apos;Always&apos; : auto download mode description for activated feature without any constraints.</extracomment>
<translation>Always</translation>
</message>
</context>
<context>
<name>SettingsLdap</name>

View file

@ -496,6 +496,9 @@ bool App::hasFocus () const {
}
void App::stateChanged(Qt::ApplicationState pState) {
DesktopTools::applicationStateChanged(pState);
auto core = CoreManager::getInstance();
if(core)
core->stateChanged(pState);
}
// -----------------------------------------------------------------------------

View file

@ -81,8 +81,8 @@ std::shared_ptr<linphone::Buffer> ChatMessageListener::onFileTransferSend(const
emit fileTransferSend(message, content, offset, size);
return nullptr;
}
void ChatMessageListener::onFileTransferProgressIndication (const std::shared_ptr<linphone::ChatMessage> &message, const std::shared_ptr<linphone::Content> & content, size_t offset, size_t i){
emit fileTransferProgressIndication(message, content, offset, i);
void ChatMessageListener::onFileTransferProgressIndication (const std::shared_ptr<linphone::ChatMessage> &message, const std::shared_ptr<linphone::Content> & content, size_t offset, size_t total){
emit fileTransferProgressIndication(message, content, offset, total);
}
void ChatMessageListener::onMsgStateChanged (const std::shared_ptr<linphone::ChatMessage> &message, linphone::ChatMessage::State state){
emit msgStateChanged(message, state);
@ -298,6 +298,8 @@ void ChatMessageModel::deleteEvent(){
if(mChatMessage)
mChatMessage->getChatRoom()->deleteMessage(mChatMessage);
}
void ChatMessageModel::updateFileTransferInformation(){
mContentListModel->updateContents(this);
}
@ -311,20 +313,23 @@ std::shared_ptr<linphone::Buffer> ChatMessageModel::onFileTransferSend (const st
return nullptr;
}
void ChatMessageModel::onFileTransferProgressIndication (const std::shared_ptr<linphone::ChatMessage> &message,const std::shared_ptr<linphone::Content> &content,size_t offset,size_t) {
void ChatMessageModel::onFileTransferProgressIndication (const std::shared_ptr<linphone::ChatMessage> &message,const std::shared_ptr<linphone::Content> &content,size_t offset,size_t total) {
auto contentModel = mContentListModel->getContentModel(content);
if(contentModel)
if(contentModel) {
contentModel->setFileOffset(offset);
if (total == offset && mChatMessage && !mChatMessage->isOutgoing()) {
mContentListModel->downloaded();
bool allAreDownloaded = true;
for(auto content : mContentListModel->getContents())
allAreDownloaded &= content->mWasDownloaded;
setWasDownloaded(allAreDownloaded);
App::getInstance()->getNotifier()->notifyReceivedFileMessage(message, content);
}
}
}
void ChatMessageModel::onMsgStateChanged (const std::shared_ptr<linphone::ChatMessage> &message, linphone::ChatMessage::State state) {
updateFileTransferInformation();// On message state, file transfert information Content can be changed
// File message downloaded.
if (mChatMessage && state == linphone::ChatMessage::State::FileTransferDone && !mChatMessage->isOutgoing()) {
mContentListModel->downloaded();
setWasDownloaded(true);
App::getInstance()->getNotifier()->notifyReceivedFileMessage(message);
}
emit stateChanged();
}
void ChatMessageModel::onParticipantImdnStateChanged(const std::shared_ptr<linphone::ChatMessage> & message, const std::shared_ptr<const linphone::ParticipantImdnState> & state){
@ -335,6 +340,8 @@ void ChatMessageModel::onEphemeralMessageTimerStarted(const std::shared_ptr<linp
}
void ChatMessageModel::onEphemeralMessageDeleted(const std::shared_ptr<linphone::ChatMessage> & message) {
//emit remove(mSelf.lock());
if(!isOutgoing())
mContentListModel->removeDownloadedFiles();
emit remove(this);
}
//-------------------------------------------------------------------------------------------------------

View file

@ -470,8 +470,8 @@ int ChatRoomModel::getState() const {
return mChatRoom ? (int)mChatRoom->getState() : 0;
}
bool ChatRoomModel::hasBeenLeft() const{
return mChatRoom && mChatRoom->hasBeenLeft();
bool ChatRoomModel::isReadOnly() const{
return mChatRoom && mChatRoom->isReadOnly();
}
bool ChatRoomModel::isEphemeralEnabled() const{
@ -1367,7 +1367,7 @@ void ChatRoomModel::onConferenceJoined(const std::shared_ptr<linphone::ChatRoom>
updateLastUpdateTime();
emit usernameChanged();
emit conferenceJoined(chatRoom, eventLog);
emit hasBeenLeftChanged();
emit isReadOnlyChanged();
}
void ChatRoomModel::onConferenceLeft(const std::shared_ptr<linphone::ChatRoom> & chatRoom, const std::shared_ptr<const linphone::EventLog> & eventLog){
@ -1384,7 +1384,7 @@ void ChatRoomModel::onConferenceLeft(const std::shared_ptr<linphone::ChatRoom> &
}
updateLastUpdateTime();
emit conferenceLeft(chatRoom, eventLog);
emit hasBeenLeftChanged();
emit isReadOnlyChanged();
}
}

View file

@ -133,7 +133,7 @@ public:
Q_PROPERTY(bool isComposing READ getIsRemoteComposing NOTIFY isRemoteComposingChanged)
Q_PROPERTY(QList<QString> composers READ getComposers NOTIFY isRemoteComposingChanged)
Q_PROPERTY(bool hasBeenLeft READ hasBeenLeft NOTIFY hasBeenLeftChanged)
Q_PROPERTY(bool isReadOnly READ isReadOnly NOTIFY isReadOnlyChanged)
Q_PROPERTY(QString sipAddress READ getFullPeerAddress NOTIFY fullPeerAddressChanged)
Q_PROPERTY(QString sipAddressUriOnly READ getPeerAddress NOTIFY fullPeerAddressChanged)
@ -180,7 +180,7 @@ public:
QString getAvatar () const;
int getPresenceStatus() const;
int getState() const;
bool hasBeenLeft() const;
bool isReadOnly() const;
bool isEphemeralEnabled() const;
long getEphemeralLifetime() const;
bool canBeEphemeral();
@ -320,7 +320,7 @@ signals:
void groupEnabledChanged(bool groupEnabled);
void isMeAdminChanged();
void stateChanged(int state);
void hasBeenLeftChanged();
void isReadOnlyChanged();
void ephemeralEnabledChanged();
void ephemeralLifetimeChanged();
void canBeEphemeralChanged();

View file

@ -150,6 +150,13 @@ void ContentListModel::clear(){
endResetModel();
}
void ContentListModel::removeDownloadedFiles(){
for(auto contentModel : mList){
contentModel->removeDownloadedFile();
contentModel->removeThumbnail();
}
}
std::shared_ptr<ContentModel> ContentListModel::getContentModel(std::shared_ptr<linphone::Content> content){
for(auto c : mList)
if(c->getContent() == content)

View file

@ -48,6 +48,7 @@ public:
Q_INVOKABLE void remove(ContentModel * model);
void clear();
void removeDownloadedFiles();
std::shared_ptr<ContentModel> getContentModel(std::shared_ptr<linphone::Content> content);// Return the contentModel by checking Content, or if it is the same file.
QList<std::shared_ptr<ContentModel>> getContents();

View file

@ -65,7 +65,14 @@ quint64 ContentModel::getFileSize() const{
}
QString ContentModel::getName() const{
return QString::fromStdString(mContent->getName());
QString name = QString::fromStdString(mContent->getName());
if( name == "") { // Try to find the name from file Path
QString fileName = QString::fromStdString(mContent->getFilePath());
if(fileName != ""){
name = QFileInfo(fileName).baseName();
}
}
return name;
}
QString ContentModel::getThumbnail() const{
@ -101,6 +108,7 @@ void ContentModel::setWasDownloaded(bool wasDownloaded){
void ContentModel::setContent(std::shared_ptr<linphone::Content> content){
mContent = content;
emit nameChanged();
if(isFile() || isFileEncrypted() || isFileTransfer() ){
QString path = Utils::coreStringToAppString(mContent->getFilePath());
if (!path.isEmpty())
@ -204,6 +212,13 @@ void ContentModel::removeThumbnail(){
mAppData.mData.clear();
}
void ContentModel::removeDownloadedFile(){
QString path = getFilePath();
if( path != ""){
QFile(path).remove();
}
}
void ContentModel::downloadFile(){
switch (mChatMessageModel->getState()) {
case LinphoneEnums::ChatMessageStateDelivered:

View file

@ -70,6 +70,7 @@ public:
void createThumbnail (const bool& force = false);
void removeThumbnail ();
void removeDownloadedFile();
Q_INVOKABLE void downloadFile();
Q_INVOKABLE void openFile (bool showDirectory = false);

View file

@ -180,6 +180,15 @@ void CoreManager::forceRefreshRegisters () {
void CoreManager::updateUnreadMessageCount(){
mEventCountNotifier->updateUnreadMessageCount();
}
void CoreManager::stateChanged(Qt::ApplicationState pState){
if(mCbsTimer){
if(pState == Qt::ApplicationActive)
mCbsTimer->setInterval( Constants::CbsCallInterval);
else
mCbsTimer->setInterval( Constants::CbsCallInterval * 10);
}
}
// -----------------------------------------------------------------------------
void CoreManager::sendLogs () const {

View file

@ -163,6 +163,7 @@ public:
Q_INVOKABLE void forceRefreshRegisters ();
void updateUnreadMessageCount();
void stateChanged(Qt::ApplicationState pState);
Q_INVOKABLE void sendLogs () const;
Q_INVOKABLE void cleanLogs () const;

View file

@ -295,16 +295,16 @@ void Notifier::notifyReceivedMessage (const shared_ptr<linphone::ChatMessage> &m
CREATE_NOTIFICATION(Notifier::ReceivedMessage, map)
}
void Notifier::notifyReceivedFileMessage (const shared_ptr<linphone::ChatMessage> &message) {
void Notifier::notifyReceivedFileMessage (const shared_ptr<linphone::ChatMessage> &message, const shared_ptr<linphone::Content> &content) {
QVariantMap map;
shared_ptr<linphone::ChatRoom> chatRoom(message->getChatRoom());
map["timelineModel"].setValue(CoreManager::getInstance()->getTimelineListModel()->getTimeline(chatRoom, true).get());
map["fileUri"] = Utils::coreStringToAppString(message->getFileTransferInformation()->getFilePath());
map["fileUri"] = Utils::coreStringToAppString(content->getFilePath());
if( Utils::getImage(map["fileUri"].toString()).isNull())
map["imageUri"] = "";
else
map["imageUri"] = map["fileUri"];
map["fileSize"] = quint64(message->getFileTransferInformation()->getSize() +message->getFileTransferInformation()->getFileSize());
map["fileSize"] = quint64(content->getSize() + content->getFileSize());
CREATE_NOTIFICATION(Notifier::ReceivedFileMessage, map)
}

View file

@ -55,7 +55,7 @@ public:
};
void notifyReceivedMessage (const std::shared_ptr<linphone::ChatMessage> &message);
void notifyReceivedFileMessage (const std::shared_ptr<linphone::ChatMessage> &message);
void notifyReceivedFileMessage (const std::shared_ptr<linphone::ChatMessage> &message, const std::shared_ptr<linphone::Content> &content);
void notifyReceivedCall (const std::shared_ptr<linphone::Call> &call);
void notifyNewVersionAvailable (const QString &version, const QString &url);
void notifySnapshotWasTaken (const QString &filePath);

View file

@ -649,6 +649,15 @@ void SettingsModel::setAutomaticallyRecordCalls (bool status) {
emit automaticallyRecordCallsChanged(status);
}
int SettingsModel::getAutoDownloadMaxSize() const{
return CoreManager::getInstance()->getCore()->getMaxSizeForAutoDownloadIncomingFiles();
}
void SettingsModel::setAutoDownloadMaxSize(int maxSize){
CoreManager::getInstance()->getCore()->setMaxSizeForAutoDownloadIncomingFiles(maxSize);
emit autoDownloadMaxSizeChanged(maxSize);
}
// -----------------------------------------------------------------------------
bool SettingsModel::getCallPauseEnabled () const {

View file

@ -109,6 +109,7 @@ class SettingsModel : public QObject {
Q_PROPERTY(bool callRecorderEnabled READ getCallRecorderEnabled WRITE setCallRecorderEnabled NOTIFY callRecorderEnabledChanged)
Q_PROPERTY(bool automaticallyRecordCalls READ getAutomaticallyRecordCalls WRITE setAutomaticallyRecordCalls NOTIFY automaticallyRecordCallsChanged)
Q_PROPERTY(int autoDownloadMaxSize READ getAutoDownloadMaxSize WRITE setAutoDownloadMaxSize NOTIFY autoDownloadMaxSizeChanged)
Q_PROPERTY(bool callPauseEnabled READ getCallPauseEnabled WRITE setCallPauseEnabled NOTIFY callPauseEnabledChanged)
Q_PROPERTY(bool muteMicrophoneEnabled READ getMuteMicrophoneEnabled WRITE setMuteMicrophoneEnabled NOTIFY muteMicrophoneEnabledChanged)
@ -357,6 +358,9 @@ public:
bool getAutomaticallyRecordCalls () const;
void setAutomaticallyRecordCalls (bool status);
int getAutoDownloadMaxSize() const;
void setAutoDownloadMaxSize(int maxSize);
bool getCallPauseEnabled () const;
void setCallPauseEnabled (bool status);
@ -625,6 +629,7 @@ signals:
void callRecorderEnabledChanged (bool status);
void automaticallyRecordCallsChanged (bool status);
void autoDownloadMaxSizeChanged (int maxSize);
void callPauseEnabledChanged (bool status);
void muteMicrophoneEnabledChanged (bool status);

View file

@ -309,7 +309,7 @@ void TimelineListModel::remove(std::shared_ptr<TimelineModel> model){
}
}
void TimelineListModel::removeChatRoomModel(std::shared_ptr<ChatRoomModel> model){
if(!model || (model->getChatRoom()->isEmpty() && (model->hasBeenLeft() || !model->isGroupEnabled()))){
if(!model || (model->getChatRoom()->isEmpty() && (model->isReadOnly() || !model->isGroupEnabled()))){
auto itTimeline = mTimelines.begin();
while(itTimeline != mTimelines.end()) {
if((*itTimeline)->mChatRoomModel == model){

View file

@ -129,7 +129,7 @@ void TimelineModel::setSelected(const bool& selected){
<< ", ephemeralEnabled:" << mChatRoomModel->isEphemeralEnabled()
<< ", isAdmin:"<< mChatRoomModel->isMeAdmin()
<< ", canHandleParticipants:"<< mChatRoomModel->canHandleParticipants()
<< ", hasBeenLeft:" << mChatRoomModel->hasBeenLeft();
<< ", isReadOnly:" << mChatRoomModel->isReadOnly();
}
emit selectedChanged(mSelected);
}

View file

@ -459,12 +459,12 @@ Rectangle {
Layout.leftMargin: ChatStyle.sendArea.backgroundBorder.width
borderColor: ChatStyle.sendArea.border.color
topWidth: ChatStyle.sendArea.border.width
visible: proxyModel.chatRoomModel && !proxyModel.chatRoomModel.hasBeenLeft && (!proxyModel.chatRoomModel.haveEncryption && SettingsModel.standardChatEnabled || proxyModel.chatRoomModel.haveEncryption && SettingsModel.secureChatEnabled)
visible: proxyModel.chatRoomModel && !proxyModel.chatRoomModel.isReadOnly && (!proxyModel.chatRoomModel.haveEncryption && SettingsModel.standardChatEnabled || proxyModel.chatRoomModel.haveEncryption && SettingsModel.secureChatEnabled)
DroppableTextArea {
id: textArea
enabled:proxyModel && proxyModel.chatRoomModel ? !proxyModel.chatRoomModel.hasBeenLeft:false
enabled:proxyModel && proxyModel.chatRoomModel ? !proxyModel.chatRoomModel.isReadOnly:false
isEphemeral : proxyModel && proxyModel.chatRoomModel ? proxyModel.chatRoomModel.ephemeralEnabled:false
anchors.left: parent.left

View file

@ -246,7 +246,7 @@ Row {
icon: ChatStyle.entry.message.file.download.icon
iconSize: ChatStyle.entry.message.file.download.iconSize
overwriteColor: isOutgoing ? ChatStyle.entry.message.file.download.outgoingColor : ChatStyle.entry.message.file.download.incomingColor
visible: (mainRow.contentModel? !mainRow.contentModel.wasDownloaded : false)
visible: !progressBar.visible && (mainRow.contentModel? !mainRow.contentModel.wasDownloaded : false)
}
MouseArea {
@ -257,7 +257,10 @@ Row {
}
anchors.fill: parent
visible: downloadButton.visible || ((rectangle.isUploaded || rectangle.isRead) && !isOutgoing) || isOutgoing
visible: true
//downloadButton.visible || ((rectangle.isUploaded || rectangle.isRead) && !isOutgoing) || isOutgoing
//onVisibleChanged: console.log("Mouse of "+mainRow.contentModel.name+" / "+downloadButton.visible
// +"/"+rectangle.isUploaded +"/"+rectangle.isRead)
onClicked: {
if (Utils.pointIsInItem(this, thumbnailProvider, mouse)) {

View file

@ -178,7 +178,7 @@ ColumnLayout {
}
onUsernameClicked: {
if(!conversation.hasBeenLeft) {
if(!conversation.isReadOnly) {
usernameEdit.visible = !usernameEdit.visible
usernameEdit.forceActiveFocus()
}
@ -198,7 +198,7 @@ ColumnLayout {
iconSize:30
MouseArea{
anchors.fill:parent
visible: !conversation.hasBeenLeft
visible: !conversation.isReadOnly
onClicked : {
window.detachVirtualWindow()
window.attachVirtualWindow(Qt.resolvedUrl('Dialogs/InfoEncryption.qml')
@ -294,7 +294,7 @@ ColumnLayout {
backgroundRadius: 1000
colorSet: ConversationStyle.bar.actions.groupChat
visible: SettingsModel.outgoingCallsEnabled && conversation.haveMoreThanOneParticipants && conversation.haveLessThanMinParticipantsForCall && !conversation.hasBeenLeft
visible: SettingsModel.outgoingCallsEnabled && conversation.haveMoreThanOneParticipants && conversation.haveLessThanMinParticipantsForCall && !conversation.isReadOnly
onClicked: Logic.openConferenceManager({chatRoomModel:conversation.chatRoomModel, autoCall:true})
//: "Call all chat room's participants" : tooltip on a button for calling all participant in the current chat room

View file

@ -27,7 +27,7 @@ DialogPlus {
chatRoomModel.leaveChatRoom();
exit(0)
}
enabled: !chatRoomModel.hasBeenLeft
enabled: !chatRoomModel.isReadOnly
visible: !chatRoomModel.isOneToOne
},Item{
Layout.fillWidth: true
@ -38,7 +38,7 @@ DialogPlus {
capitalization: Font.AllUppercase
onClicked: {
if(!chatRoomModel.hasBeenLeft)
if(!chatRoomModel.isReadOnly)
chatRoomModel.updateParticipants(selectedParticipants.getParticipants()) // Remove/New
exit(1)
}
@ -58,7 +58,7 @@ DialogPlus {
height: InfoChatRoomStyle.height
width: InfoChatRoomStyle.width
readonly property bool adminMode : chatRoomModel.isMeAdmin && !chatRoomModel.hasBeenLeft
readonly property bool adminMode : chatRoomModel.isMeAdmin && !chatRoomModel.isReadOnly
// ---------------------------------------------------------------------------
ColumnLayout {

View file

@ -1,10 +1,12 @@
import QtQuick 2.7
import QtQuick.Layouts 1.3
import Common 1.0
import Linphone 1.0
import Utils 1.0
import App.Styles 1.0
import Common.Styles 1.0
// =============================================================================
@ -240,7 +242,7 @@ TabContainer {
onClicked: SettingsModel.secureChatEnabled = !checked
}
}
FormGroup {
label: qsTr('conferenceEnabledLabel')
@ -316,6 +318,79 @@ TabContainer {
}
}
}
FormLine {
FormGroup {
//: 'Auto download' : Label for a slider about auto download mode
label: qsTr('AutoDownload')
RowLayout{
Layout.fillHeight: true
Layout.fillWidth: true
spacing: 0
Slider {
Layout.fillHeight: true
Layout.fillWidth: true
id: autoDownloadModes
width: parent.width
function toSlider(value){
if( value == -1)
return autoDownloadModes.from;
else if(value == 0)
return autoDownloadModes.to;
else
return value/1000000+autoDownloadModes.from
}
function fromSlider(value){
if( value == autoDownloadModes.from)
return -1
else if( value == autoDownloadModes.to)
return 0
else
return (value - autoDownloadModes.from) * 1000000
}
onValueChanged: {
SettingsModel.autoDownloadMaxSize = fromSlider(value)
autoDownloadText.updateText(value)
}
from: 1
to: 500
stepSize: 1
value: toSlider(SettingsModel.autoDownloadMaxSize)
}
Text {
id: autoDownloadText
property int preferredWidth : 0
Layout.preferredWidth: preferredWidth
color: FormHGroupStyle.legend.color
font.pointSize: FormHGroupStyle.legend.pointSize
function updateText(value){
//: 'Never' : auto download mode description for deactivated feature.
text = value == autoDownloadModes.from ? qsTr('autoDownloadNever')
//: 'Always' : auto download mode description for activated feature without any constraints.
: value == autoDownloadModes.to ? qsTr('autoDownloadAlways')
: ' < '+ ( autoDownloadModes.fromSlider(value) ).toFixed(0)/1000000 + ' Mb'
}
Component.onCompleted: updateMaxSize()
function updateMaxSize(){
autoDownloadText.visible = false
updateText(autoDownloadModes.from)
var maxWidth = autoDownloadText.implicitWidth
updateText(autoDownloadModes.to)
maxWidth = Math.max( maxWidth, autoDownloadText.implicitWidth)
updateText(autoDownloadModes.to-1)
maxWidth = Math.max( maxWidth, autoDownloadText.implicitWidth)
autoDownloadText.preferredWidth = maxWidth
updateText(autoDownloadModes.value)
autoDownloadText.visible = true
}
}
}
}
}
FormLine {

@ -1 +1 @@
Subproject commit 9b46b4998337f0e80daeca2030b5ccad120d8724
Subproject commit e198368c1254aff728c643ce8cba1541cdb5dc10