Merge 84baa370a98e93f10cdaecfbf7a141f1181f7183 into 590fd624a4d7ddd4fed6de4113129e08e71d262a

This commit is contained in:
Корней Гедерт 2024-12-02 16:41:16 +00:00 committed by GitHub
commit 92afd2a71f
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
13 changed files with 625 additions and 28 deletions

View File

@ -196,6 +196,9 @@ set(HEADERS
common/preferencestreeproxymodel.h
common/preferenceswidget.h
common/inputmessagenotifier.h
common/inputdetectors.h
)
set(SOURCES
@ -378,6 +381,9 @@ set(SOURCES
common/preferencestreeproxymodel.cpp
common/preferenceswidget.cpp
common/inputmessagenotifier.cpp
common/inputdetectors.cpp
)
set(UI_FORMS

View File

@ -764,6 +764,37 @@ context (user policy option)</translation>
<translation>Common</translation>
</message>
</context>
<context>
<name>preferences::InputMessageNotifier</name>
<message>
<source>The input field has a space at the beginning or at the end</source>
<translation type="vanished">The input field has a space at the beginning or at the end</translation>
</message>
<message>
<source>There is a folder &apos;.&apos;/&apos;..&apos; in the path input field</source>
<translation type="vanished">There is a folder &apos;.&apos;/&apos;..&apos; in the path input field</translation>
</message>
<message>
<source>The path input field contains the path to the folder</source>
<translation type="vanished">The path input field contains the path to the folder</translation>
</message>
<message>
<source>The path input field contains a path that is not compatible with windows</source>
<translation type="vanished">The path input field contains a path that is not compatible with windows</translation>
</message>
<message>
<source>The path input field contains a relative path</source>
<translation type="vanished">The path input field contains a relative path</translation>
</message>
<message>
<source>The path input field contains a path from root</source>
<translation type="vanished">The path input field contains a path from root</translation>
</message>
<message>
<source>The path input field contains a network path</source>
<translation type="vanished">The path input field contains a network path</translation>
</message>
</context>
<context>
<name>preferences::PreferencesTreeView</name>
<message>

View File

@ -765,6 +765,37 @@ context (user policy option)</source>
<translation>Общие</translation>
</message>
</context>
<context>
<name>preferences::InputMessageNotifier</name>
<message>
<source>The input field has a space at the beginning or at the end</source>
<translation type="vanished">Поле ввода содержит пробел в начале или в конце</translation>
</message>
<message>
<source>There is a folder &apos;.&apos;/&apos;..&apos; in the path input field</source>
<translation type="vanished">В поле ввода пути есть папка &quot;.&quot;/&quot;..&quot;</translation>
</message>
<message>
<source>The path input field contains the path to the folder</source>
<translation type="vanished">Поле ввода пути содержит путь к папке</translation>
</message>
<message>
<source>The path input field contains a path that is not compatible with windows</source>
<translation type="vanished">Поле ввода path содержит путь, который несовместим с Windows</translation>
</message>
<message>
<source>The path input field contains a relative path</source>
<translation type="vanished">Поле ввода path содержит относительный путь</translation>
</message>
<message>
<source>The path input field contains a path from root</source>
<translation type="vanished">Поле ввода path содержит путь от корня</translation>
</message>
<message>
<source>The path input field contains a network path</source>
<translation type="vanished">Поле ввода path содержит сетевой путь</translation>
</message>
</context>
<context>
<name>preferences::PreferencesTreeView</name>
<message>

View File

@ -0,0 +1,15 @@
#include "inputdetectors.h"
namespace preferences {
bool WhitespaceDetector::detect(const QString &input)
{
return input.trimmed() != input;
}
bool EmptyDetector::detect(const QString &input)
{
return input.length() == 0;
}
} // namespace preferences

View File

@ -0,0 +1,42 @@
/***********************************************************************************************************************
**
** Copyright (C) 2021 BaseALT Ltd. <org@basealt.ru>
**
** 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 2
** 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.
**
***********************************************************************************************************************/
#ifndef GPUI_INPUTDETECTORS_H
#define GPUI_INPUTDETECTORS_H
#include "inputmessagenotifier.h"
namespace preferences {
class WhitespaceDetector : public InputDetector
{
public:
bool detect(const QString &input) override;
};
class EmptyDetector : public InputDetector
{
public:
bool detect(const QString &input) override;
};
} // namespace preferences
#endif // GPUI_INPUTDETECTORS_H

View File

@ -0,0 +1,206 @@
/***********************************************************************************************************************
**
** Copyright (C) 2021 BaseALT Ltd. <org@basealt.ru>
**
** 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 2
** 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.
**
***********************************************************************************************************************/
#include "inputmessagenotifier.h"
#include <algorithm>
#include <iterator>
namespace preferences {
InputMessageNotifier::DetectElement::DetectElement(QWidget *parent, QLayout *layout,
const QString &message,
InputMessageNotifier::MessageLevel level)
{
this->m_label = new QLabel(parent);
layout->addWidget(this->m_label);
this->m_label->hide();
this->m_label->setText(message);
switch (level) {
case InputMessageNotifier::MessageLevel::Warning:
this->m_label->setStyleSheet("background-color: rgb(249, 240, 107);\n"
"color: rgb(0,0,0);\n"
"border-radius: 10px;\n"
"padding: 10px;");
break;
default:
case InputMessageNotifier::MessageLevel::Error:
this->m_label->setStyleSheet("background-color: rgb(246, 97, 81);\n"
"color: rgb(255, 255, 255);\n"
"border-radius: 10px;\n"
"padding: 10px;");
break;
}
this->m_level = level;
}
InputMessageNotifier::DetectElement::DetectElement(DetectElement &&element)
{
this->m_detected = element.m_detected;
this->m_label = element.m_label;
this->m_level = element.m_level;
element.m_label = nullptr;
}
InputMessageNotifier::DetectElement &
InputMessageNotifier::DetectElement::operator=(DetectElement &&element)
{
if (this->m_label) {
delete this->m_label;
}
this->m_detected = element.m_detected;
this->m_label = element.m_label;
this->m_level = element.m_level;
element.m_label = nullptr;
return *this;
}
void InputMessageNotifier::DetectElement::detect()
{
this->m_label->show();
this->m_detected = true;
}
void InputMessageNotifier::DetectElement::undetect()
{
this->m_label->hide();
this->m_detected = false;
}
bool InputMessageNotifier::DetectElement::detected()
{
return this->m_detected;
}
InputMessageNotifier::MessageLevel InputMessageNotifier::DetectElement::level()
{
return this->m_level;
}
void InputMessageNotifier::DetectElement::setMessage(const QString &message)
{
this->m_label->setText(message);
}
InputMessageNotifier::DetectElement::~DetectElement()
{
if (this->m_label) {
delete this->m_label;
}
}
InputMessageNotifier::InputMessageNotifier(QWidget *widget) : QWidget(widget)
{
this->m_layout = new QVBoxLayout;
this->setLayout(this->m_layout);
}
size_t InputMessageNotifier::addDetector(std::unique_ptr<InputDetector> detector)
{
this->m_detectors[this->m_nextDetector] = std::move(detector);
return this->m_nextDetector++;
}
void InputMessageNotifier::removeDetector(size_t id)
{
this->m_detectors.erase(id);
}
void InputMessageNotifier::addInput(const QString &name)
{
this->m_instances[name] = std::move(InputInstance());
}
void InputMessageNotifier::removeInput(const QString &name)
{
this->m_instances.erase(name);
}
void InputMessageNotifier::updateInput(const QString &name, const QString &input)
{
auto &instance = this->m_instances[name];
for (auto &detect : instance) {
bool detected = this->m_detectors[detect.first]->detect(input);
if (detected && !detect.second.detected()) {
detect.second.detect();
this->incCounter(detect.second.level());
} else if (!detected && detect.second.detected()) {
detect.second.undetect();
this->decCounter(detect.second.level());
}
}
}
void InputMessageNotifier::setMessage(const QString &name, size_t detector, const QString &message)
{
auto entry = this->m_instances[name].find(detector);
if (entry != this->m_instances[name].end()) {
entry->second.setMessage(message);
}
}
void InputMessageNotifier::attachDetector(const QString &name, size_t detector,
const QString &message, MessageLevel level)
{
this->m_instances[name].insert(std::pair<size_t, DetectElement>(
detector, DetectElement(this, this->m_layout, message, level)));
}
bool InputMessageNotifier::hasAnyError()
{
return this->m_errorCount != 0;
}
bool InputMessageNotifier::hasAnyWarning()
{
return this->m_warningCount != 0;
}
InputMessageNotifier::~InputMessageNotifier() { }
void InputMessageNotifier::incCounter(InputMessageNotifier::MessageLevel level)
{
switch (level) {
case InputMessageNotifier::MessageLevel::Warning:
++this->m_warningCount;
break;
case InputMessageNotifier::MessageLevel::Error:
++this->m_errorCount;
break;
}
}
void InputMessageNotifier::decCounter(MessageLevel level)
{
switch (level) {
case InputMessageNotifier::MessageLevel::Warning:
--this->m_warningCount;
break;
case InputMessageNotifier::MessageLevel::Error:
--this->m_errorCount;
break;
}
}
} // namespace preferences

View File

@ -0,0 +1,164 @@
/***********************************************************************************************************************
**
** Copyright (C) 2021 BaseALT Ltd. <org@basealt.ru>
**
** 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 2
** 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.
**
***********************************************************************************************************************/
#ifndef GPUI_INPUTMESSAGENOTIFIER_H
#define GPUI_INPUTMESSAGENOTIFIER_H
#include <QtCore>
#include <QtWidgets>
#include <bits/stdc++.h>
namespace preferences {
class InputDetector
{
public:
virtual bool detect(const QString &input) = 0;
virtual ~InputDetector() = default;
};
class InputMessageNotifier : public QWidget
{
public:
Q_OBJECT
public:
enum class MessageLevel {
Warning,
Error,
};
private:
typedef struct DetectElement
{
public:
DetectElement(QWidget *parent, QLayout *layout, const QString &message, MessageLevel level);
DetectElement(DetectElement &&element);
DetectElement &operator=(DetectElement &&element);
void detect();
void undetect();
bool detected();
MessageLevel level();
void setMessage(const QString &message);
~DetectElement();
private:
DetectElement(const DetectElement &) = delete; // copy ctor
DetectElement &operator=(const DetectElement &) = delete; // copy assignment
private:
bool m_detected{ false };
QLabel *m_label{ nullptr };
MessageLevel m_level{ MessageLevel::Warning };
} DetectElement;
typedef std::unordered_map<size_t, DetectElement> InputInstance;
public:
InputMessageNotifier(QWidget *widget);
/**
* @brief add detector.
* @param detector Detector.
* @return Detector id.
*/
size_t addDetector(std::unique_ptr<InputDetector> detector);
/**
* @brief remove detector.
* @param id Detector id.
*/
void removeDetector(size_t id);
/**
* @brief registrate input.
* @param name Name of input to be registrated.
*/
void addInput(const QString &name);
/**
* @brief unregistrate input.
* @param name Name of input to be unregistrated.
*/
void removeInput(const QString &name);
/**
* @brief update input content and validate it.
* @param name Name of registrated input.
* @param input Input content.
*/
void updateInput(const QString &name, const QString &input);
/**
* @brief update input content and validate it.
* @param name Name of registrated input.
* @param detector Detector id.
* @param message MessageNotifier message on detect.
*/
void setMessage(const QString &name, size_t detector, const QString &message);
/**
* @brief attach detector to input.
* @param name Name of registrated input.
* @param detector Detector id.
* @param level Message level(visual and see hasAnyError() and hasAnyWarning())
*/
void attachDetector(const QString &name, size_t detector, const QString &message,
MessageLevel level = MessageLevel::Warning);
/**
* @return true, if any error has been detected(on any input).
*/
bool hasAnyError();
/**
* @return true, if any warning has been detected(on any input).
*/
bool hasAnyWarning();
~InputMessageNotifier();
private:
InputMessageNotifier(const InputMessageNotifier &) = delete; // copy ctor
InputMessageNotifier(InputMessageNotifier &&) = delete; // move ctor
InputMessageNotifier &operator=(const InputMessageNotifier &) = delete; // copy assignment
InputMessageNotifier &operator=(InputMessageNotifier &&) = delete; // move assignment
void incCounter(MessageLevel level);
void decCounter(MessageLevel level);
private:
std::unordered_map<size_t, std::unique_ptr<InputDetector>> m_detectors{};
std::unordered_map<QString, InputInstance> m_instances{};
size_t m_errorCount{ 0 };
size_t m_warningCount{ 0 };
size_t m_nextDetector{ 0 };
QLayout *m_layout{ nullptr };
};
} // namespace preferences
#endif // GPUI_INPUTMESSAGENOTIFIER_H

View File

@ -20,6 +20,7 @@
#include "fileswidget.h"
#include "ui_fileswidget.h"
#include "common/inputdetectors.h"
#include "common/commonutils.h"
#include "filesitem.h"
@ -40,6 +41,20 @@ FilesWidget::FilesWidget(QWidget *parent, FilesItem *item)
{
ui->setupUi(this);
this->whitespaceDetector = ui->inputMessage->addDetector(std::unique_ptr<InputDetector>(new WhitespaceDetector));
this->emptyDetector = ui->inputMessage->addDetector(std::unique_ptr<InputDetector>(new EmptyDetector));
ui->inputMessage->addInput("source_file");
ui->inputMessage->addInput("destination");
ui->inputMessage->attachDetector("source_file", whitespaceDetector, tr("source_file_whitespace"));
ui->inputMessage->attachDetector("source_file", emptyDetector, tr("source_file_empty"), InputMessageNotifier::MessageLevel::Error);
ui->inputMessage->attachDetector("destination", whitespaceDetector, tr("destination_whitespace"));
ui->inputMessage->attachDetector("destination", emptyDetector, tr("destination_empty"), InputMessageNotifier::MessageLevel::Error);
ui->sourceLineEdit->setToolTip("test");
on_actionComboBox_currentIndexChanged(ui->actionComboBox->currentIndex());
}

View File

@ -65,6 +65,7 @@ private slots:
void on_actionComboBox_currentIndexChanged(int index);
void on_destinationToolButton_clicked();
void on_sourceLineEdit_textChanged(const QString &text);
void on_destinationLineEdit_textChanged(const QString &text);
void on_sourceToolButton_clicked();
private:
@ -82,6 +83,9 @@ private:
bool fileMode {true};
size_t whitespaceDetector{0};
size_t emptyDetector{0};
private:
Ui::FilesWidget *ui {nullptr};
};

View File

@ -117,6 +117,9 @@
</item>
</layout>
</item>
<item>
<widget class="preferences::InputMessageNotifier" name="inputMessage" native="true"/>
</item>
<item>
<widget class="QCheckBox" name="supressErrorsCheckBox">
<property name="text">
@ -202,6 +205,12 @@
<extends>QLineEdit</extends>
<header>common/shortcutlineedit.h</header>
</customwidget>
<customwidget>
<class>preferences::InputMessageNotifier</class>
<extends>QWidget</extends>
<header>common/inputmessagenotifier.h</header>
<container>1</container>
</customwidget>
</customwidgets>
<resources/>
<connections/>

View File

@ -103,6 +103,11 @@ void FilesWidget::on_destinationToolButton_clicked()
}
}
void FilesWidget::on_destinationLineEdit_textChanged(const QString &text)
{
ui->inputMessage->updateInput("destination", text);
}
void FilesWidget::on_sourceLineEdit_textChanged(const QString &text)
{
if (text.contains('*') || text.contains('?'))
@ -110,13 +115,18 @@ void FilesWidget::on_sourceLineEdit_textChanged(const QString &text)
fileMode = false;
ui->destinationLabel->setText(tr("Destination folder:"));
ui->inputMessage->setMessage("destination", this->whitespaceDetector, tr("destination_folder_whitespace"));
ui->inputMessage->setMessage("destination", this->emptyDetector, tr("destination_folder_empty"));
}
else
{
fileMode = true;
ui->destinationLabel->setText(tr("Destination file:"));
ui->inputMessage->setMessage("destination", this->whitespaceDetector, tr("destination_whitespace"));
ui->inputMessage->setMessage("destination", this->emptyDetector, tr("destination_empty"));
}
ui->inputMessage->updateInput("source_file", text);
}
} // namespace preferences

View File

@ -57,32 +57,32 @@
<translation>Destination:</translation>
</message>
<message>
<location filename="../fileswidget.ui" line="123"/>
<location filename="../fileswidget.ui" line="126"/>
<source>Supress errors on individual file actions</source>
<translation>Supress errors on individual file actions</translation>
</message>
<message>
<location filename="../fileswidget.ui" line="147"/>
<location filename="../fileswidget.ui" line="150"/>
<source>Attributes</source>
<translation>Attributes</translation>
</message>
<message>
<location filename="../fileswidget.ui" line="153"/>
<location filename="../fileswidget.ui" line="156"/>
<source>Read-only</source>
<translation>Read-only</translation>
</message>
<message>
<location filename="../fileswidget.ui" line="160"/>
<location filename="../fileswidget.ui" line="163"/>
<source>Hidden</source>
<translation>Hidden</translation>
</message>
<message>
<location filename="../fileswidget.ui" line="167"/>
<location filename="../fileswidget.ui" line="170"/>
<source>Archive</source>
<translation>Archive</translation>
</message>
<message>
<location filename="../fileswidget.ui" line="174"/>
<location filename="../fileswidget.ui" line="177"/>
<source>Executable</source>
<translation>Executable</translation>
</message>
@ -120,13 +120,13 @@
<translation>Target</translation>
</message>
<message>
<location filename="../fileswidgetslots.cpp" line="79"/>
<location filename="../fileswidgetslots.cpp" line="86"/>
<location filename="../fileswidgetslots.cpp" line="80"/>
<location filename="../fileswidgetslots.cpp" line="91"/>
<source>All files (*)</source>
<translation>All files (*)</translation>
</message>
<message>
<location filename="../fileswidgetslots.cpp" line="90"/>
<location filename="../fileswidgetslots.cpp" line="99"/>
<source>All files (*.*)</source>
<translation>All files (*.*)</translation>
</message>
@ -134,17 +134,39 @@
<context>
<name>preferences::FilesWidget</name>
<message>
<location filename="../fileswidget.cpp" line="79"/>
<location filename="../fileswidget.cpp" line="50"/>
<location filename="../fileswidget.cpp" line="51"/>
<source>source_file_whitespace</source>
<translation>The input field of the source file contains a space at the beginning or at the end</translation>
</message>
<message>
<location filename="../fileswidgetslots.cpp" line="126"/>
<source>destination_whitespace</source>
<translation>The input field of the destination file contains a space at the beginning or at the end</translation>
</message>
<message>
<location filename="../fileswidget.cpp" line="53"/>
<source>source_file_empty</source>
<translation>An empty input field for the source file</translation>
</message>
<message>
<location filename="../fileswidget.cpp" line="54"/>
<location filename="../fileswidgetslots.cpp" line="127"/>
<source>destination_empty</source>
<translation>An empty input field for the destination file</translation>
</message>
<message>
<location filename="../fileswidget.cpp" line="92"/>
<source>Please enter source file(s) value.</source>
<translation>Please enter source file(s) value.</translation>
</message>
<message>
<location filename="../fileswidget.cpp" line="84"/>
<location filename="../fileswidget.cpp" line="97"/>
<source>Please enter destination file(s) value.</source>
<translation>Please enter destination file(s) value.</translation>
</message>
<message>
<location filename="../fileswidget.cpp" line="94"/>
<location filename="../fileswidget.cpp" line="107"/>
<source>General</source>
<translation>General</translation>
</message>
@ -155,10 +177,20 @@
</message>
<message>
<location filename="../fileswidgetslots.cpp" line="73"/>
<location filename="../fileswidgetslots.cpp" line="106"/>
<location filename="../fileswidgetslots.cpp" line="125"/>
<source>Destination file:</source>
<translation>Destination file:</translation>
</message>
<message>
<location filename="../fileswidgetslots.cpp" line="118"/>
<source>destination_folder_whitespace</source>
<translation>The input field of the destination folder contains a space at the beginning or at the end</translation>
</message>
<message>
<location filename="../fileswidgetslots.cpp" line="119"/>
<source>destination_folder_empty</source>
<translation>An empty input field for the destination folder</translation>
</message>
<message>
<source>Open</source>
<translation type="vanished">Open</translation>
@ -184,7 +216,7 @@
<translation type="vanished">Open Directory</translation>
</message>
<message>
<location filename="../fileswidgetslots.cpp" line="100"/>
<location filename="../fileswidgetslots.cpp" line="117"/>
<source>Destination folder:</source>
<translation>Destination folder:</translation>
</message>

View File

@ -57,32 +57,32 @@
<translation>Назначение:</translation>
</message>
<message>
<location filename="../fileswidget.ui" line="123"/>
<location filename="../fileswidget.ui" line="126"/>
<source>Supress errors on individual file actions</source>
<translation>Подавление ошибок при действиях с отдельными файлами</translation>
</message>
<message>
<location filename="../fileswidget.ui" line="147"/>
<location filename="../fileswidget.ui" line="150"/>
<source>Attributes</source>
<translation>Атрибуты</translation>
</message>
<message>
<location filename="../fileswidget.ui" line="153"/>
<location filename="../fileswidget.ui" line="156"/>
<source>Read-only</source>
<translation>Только для чтения</translation>
</message>
<message>
<location filename="../fileswidget.ui" line="160"/>
<location filename="../fileswidget.ui" line="163"/>
<source>Hidden</source>
<translation>Скрытый</translation>
</message>
<message>
<location filename="../fileswidget.ui" line="167"/>
<location filename="../fileswidget.ui" line="170"/>
<source>Archive</source>
<translation>Архивный</translation>
</message>
<message>
<location filename="../fileswidget.ui" line="174"/>
<location filename="../fileswidget.ui" line="177"/>
<source>Executable</source>
<translation>Исполняемый</translation>
</message>
@ -120,13 +120,13 @@
<translation>Цель</translation>
</message>
<message>
<location filename="../fileswidgetslots.cpp" line="79"/>
<location filename="../fileswidgetslots.cpp" line="86"/>
<location filename="../fileswidgetslots.cpp" line="80"/>
<location filename="../fileswidgetslots.cpp" line="91"/>
<source>All files (*)</source>
<translation>Все файлы (*)</translation>
</message>
<message>
<location filename="../fileswidgetslots.cpp" line="90"/>
<location filename="../fileswidgetslots.cpp" line="99"/>
<source>All files (*.*)</source>
<translation>Все файлы (*.*)</translation>
</message>
@ -134,17 +134,39 @@
<context>
<name>preferences::FilesWidget</name>
<message>
<location filename="../fileswidget.cpp" line="79"/>
<location filename="../fileswidget.cpp" line="50"/>
<location filename="../fileswidget.cpp" line="51"/>
<source>source_file_whitespace</source>
<translation>Поле ввода исходного файла содержит пробел в начале или в конце</translation>
</message>
<message>
<location filename="../fileswidgetslots.cpp" line="126"/>
<source>destination_whitespace</source>
<translation>Поле ввода целевого файла содержит пробел в начале или в конце</translation>
</message>
<message>
<location filename="../fileswidget.cpp" line="53"/>
<source>source_file_empty</source>
<translation>Пустое поле ввода исходного файла</translation>
</message>
<message>
<location filename="../fileswidget.cpp" line="54"/>
<location filename="../fileswidgetslots.cpp" line="127"/>
<source>destination_empty</source>
<translation>Пустое поле ввода файла назначения</translation>
</message>
<message>
<location filename="../fileswidget.cpp" line="92"/>
<source>Please enter source file(s) value.</source>
<translation>Пожалуйста, введите источник файла(ов).</translation>
</message>
<message>
<location filename="../fileswidget.cpp" line="84"/>
<location filename="../fileswidget.cpp" line="97"/>
<source>Please enter destination file(s) value.</source>
<translation>Пожалуйста, введите место назначения файла(ов).</translation>
</message>
<message>
<location filename="../fileswidget.cpp" line="94"/>
<location filename="../fileswidget.cpp" line="107"/>
<source>General</source>
<translation>Основные настройки</translation>
</message>
@ -155,10 +177,20 @@
</message>
<message>
<location filename="../fileswidgetslots.cpp" line="73"/>
<location filename="../fileswidgetslots.cpp" line="106"/>
<location filename="../fileswidgetslots.cpp" line="125"/>
<source>Destination file:</source>
<translation>Место назначения файлов:</translation>
</message>
<message>
<location filename="../fileswidgetslots.cpp" line="118"/>
<source>destination_folder_whitespace</source>
<translation>Поле ввода целевой папки содержит пробел в начале или в конце</translation>
</message>
<message>
<location filename="../fileswidgetslots.cpp" line="119"/>
<source>destination_folder_empty</source>
<translation>Пустое поле ввода папки назначения</translation>
</message>
<message>
<source>Open</source>
<translation type="vanished">Открыть</translation>
@ -184,7 +216,7 @@
<translation type="vanished">Открыть Директорию</translation>
</message>
<message>
<location filename="../fileswidgetslots.cpp" line="100"/>
<location filename="../fileswidgetslots.cpp" line="117"/>
<source>Destination folder:</source>
<translation>Папка назначения:</translation>
</message>