mirror of https://github.com/procxx/kepka.git
Warn before running executable files.
This commit is contained in:
parent
edadc51e05
commit
b10ccce44a
|
@ -1825,6 +1825,10 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||||
"lng_language_not_ready_about" = "Unfortunately, this custom language pack ({lang_name}) doesn't contain data for Telegram Desktop. You can contribute to this language pack using the {link}.";
|
"lng_language_not_ready_about" = "Unfortunately, this custom language pack ({lang_name}) doesn't contain data for Telegram Desktop. You can contribute to this language pack using the {link}.";
|
||||||
"lng_language_not_ready_link" = "translations platform";
|
"lng_language_not_ready_link" = "translations platform";
|
||||||
|
|
||||||
|
"lng_launch_exe_warning" = "This file has a {extension} extension.\nAre you sure you want to run it?";
|
||||||
|
"lng_launch_exe_sure" = "Run";
|
||||||
|
"lng_launch_exe_dont_ask" = "Don't ask me again";
|
||||||
|
|
||||||
// Wnd specific
|
// Wnd specific
|
||||||
|
|
||||||
"lng_wnd_choose_program_menu" = "Choose Default Program...";
|
"lng_wnd_choose_program_menu" = "Choose Default Program...";
|
||||||
|
|
|
@ -45,7 +45,7 @@ AuthSessionSettings::Variables::Variables()
|
||||||
}
|
}
|
||||||
|
|
||||||
QByteArray AuthSessionSettings::serialize() const {
|
QByteArray AuthSessionSettings::serialize() const {
|
||||||
auto size = sizeof(qint32) * 10;
|
auto size = sizeof(qint32) * 23;
|
||||||
for (auto i = _variables.soundOverrides.cbegin(), e = _variables.soundOverrides.cend(); i != e; ++i) {
|
for (auto i = _variables.soundOverrides.cbegin(), e = _variables.soundOverrides.cend(); i != e; ++i) {
|
||||||
size += Serialize::stringSize(i.key()) + Serialize::stringSize(i.value());
|
size += Serialize::stringSize(i.key()) + Serialize::stringSize(i.value());
|
||||||
}
|
}
|
||||||
|
@ -87,6 +87,7 @@ QByteArray AuthSessionSettings::serialize() const {
|
||||||
stream << qint32(_variables.supportChatsTimeSlice.current());
|
stream << qint32(_variables.supportChatsTimeSlice.current());
|
||||||
stream << qint32(_variables.includeMutedCounter ? 1 : 0);
|
stream << qint32(_variables.includeMutedCounter ? 1 : 0);
|
||||||
stream << qint32(_variables.countUnreadMessages ? 1 : 0);
|
stream << qint32(_variables.countUnreadMessages ? 1 : 0);
|
||||||
|
stream << qint32(_variables.exeLaunchWarning ? 1 : 0);
|
||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
@ -120,6 +121,7 @@ void AuthSessionSettings::constructFromSerialized(const QByteArray &serialized)
|
||||||
qint32 supportChatsTimeSlice = _variables.supportChatsTimeSlice.current();
|
qint32 supportChatsTimeSlice = _variables.supportChatsTimeSlice.current();
|
||||||
qint32 includeMutedCounter = _variables.includeMutedCounter ? 1 : 0;
|
qint32 includeMutedCounter = _variables.includeMutedCounter ? 1 : 0;
|
||||||
qint32 countUnreadMessages = _variables.countUnreadMessages ? 1 : 0;
|
qint32 countUnreadMessages = _variables.countUnreadMessages ? 1 : 0;
|
||||||
|
qint32 exeLaunchWarning = _variables.exeLaunchWarning ? 1 : 0;
|
||||||
|
|
||||||
stream >> selectorTab;
|
stream >> selectorTab;
|
||||||
stream >> lastSeenWarningSeen;
|
stream >> lastSeenWarningSeen;
|
||||||
|
@ -190,6 +192,9 @@ void AuthSessionSettings::constructFromSerialized(const QByteArray &serialized)
|
||||||
stream >> includeMutedCounter;
|
stream >> includeMutedCounter;
|
||||||
stream >> countUnreadMessages;
|
stream >> countUnreadMessages;
|
||||||
}
|
}
|
||||||
|
if (!stream.atEnd()) {
|
||||||
|
stream >> exeLaunchWarning;
|
||||||
|
}
|
||||||
if (stream.status() != QDataStream::Ok) {
|
if (stream.status() != QDataStream::Ok) {
|
||||||
LOG(("App Error: "
|
LOG(("App Error: "
|
||||||
"Bad data for AuthSessionSettings::constructFromSerialized()"));
|
"Bad data for AuthSessionSettings::constructFromSerialized()"));
|
||||||
|
@ -253,6 +258,7 @@ void AuthSessionSettings::constructFromSerialized(const QByteArray &serialized)
|
||||||
_variables.hadLegacyCallsPeerToPeerNobody = (legacyCallsPeerToPeer == kLegacyCallsPeerToPeerNobody);
|
_variables.hadLegacyCallsPeerToPeerNobody = (legacyCallsPeerToPeer == kLegacyCallsPeerToPeerNobody);
|
||||||
_variables.includeMutedCounter = (includeMutedCounter == 1);
|
_variables.includeMutedCounter = (includeMutedCounter == 1);
|
||||||
_variables.countUnreadMessages = (countUnreadMessages == 1);
|
_variables.countUnreadMessages = (countUnreadMessages == 1);
|
||||||
|
_variables.exeLaunchWarning = (exeLaunchWarning == 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
void AuthSessionSettings::setSupportChatsTimeSlice(int slice) {
|
void AuthSessionSettings::setSupportChatsTimeSlice(int slice) {
|
||||||
|
|
|
@ -199,6 +199,12 @@ public:
|
||||||
void setCountUnreadMessages(bool value) {
|
void setCountUnreadMessages(bool value) {
|
||||||
_variables.countUnreadMessages = value;
|
_variables.countUnreadMessages = value;
|
||||||
}
|
}
|
||||||
|
bool exeLaunchWarning() const {
|
||||||
|
return _variables.exeLaunchWarning;
|
||||||
|
}
|
||||||
|
void setExeLaunchWarning(bool warning) {
|
||||||
|
_variables.exeLaunchWarning = warning;
|
||||||
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
struct Variables {
|
struct Variables {
|
||||||
|
@ -227,6 +233,7 @@ private:
|
||||||
bool hadLegacyCallsPeerToPeerNobody = false;
|
bool hadLegacyCallsPeerToPeerNobody = false;
|
||||||
bool includeMutedCounter = true;
|
bool includeMutedCounter = true;
|
||||||
bool countUnreadMessages = true;
|
bool countUnreadMessages = true;
|
||||||
|
bool exeLaunchWarning = true;
|
||||||
|
|
||||||
static constexpr auto kDefaultSupportChatsLimitSlice
|
static constexpr auto kDefaultSupportChatsLimitSlice
|
||||||
= 7 * 24 * 60 * 60;
|
= 7 * 24 * 60 * 60;
|
||||||
|
|
|
@ -145,6 +145,16 @@ void BoxContent::onInnerResize() {
|
||||||
updateShadowsVisibility();
|
updateShadowsVisibility();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void BoxContent::setDimensionsToContent(
|
||||||
|
int newWidth,
|
||||||
|
not_null<Ui::RpWidget*> content) {
|
||||||
|
content->resizeToWidth(newWidth);
|
||||||
|
content->heightValue(
|
||||||
|
) | rpl::start_with_next([=](int height) {
|
||||||
|
setDimensions(newWidth, height);
|
||||||
|
}, content->lifetime());
|
||||||
|
}
|
||||||
|
|
||||||
void BoxContent::setInnerTopSkip(int innerTopSkip, bool scrollBottomFixed) {
|
void BoxContent::setInnerTopSkip(int innerTopSkip, bool scrollBottomFixed) {
|
||||||
if (_innerTopSkip != innerTopSkip) {
|
if (_innerTopSkip != innerTopSkip) {
|
||||||
auto delta = innerTopSkip - _innerTopSkip;
|
auto delta = innerTopSkip - _innerTopSkip;
|
||||||
|
|
|
@ -152,6 +152,9 @@ protected:
|
||||||
void setDimensions(int newWidth, int maxHeight) {
|
void setDimensions(int newWidth, int maxHeight) {
|
||||||
getDelegate()->setDimensions(newWidth, maxHeight);
|
getDelegate()->setDimensions(newWidth, maxHeight);
|
||||||
}
|
}
|
||||||
|
void setDimensionsToContent(
|
||||||
|
int newWidth,
|
||||||
|
not_null<Ui::RpWidget*> content);
|
||||||
void setInnerTopSkip(int topSkip, bool scrollBottomFixed = false);
|
void setInnerTopSkip(int topSkip, bool scrollBottomFixed = false);
|
||||||
void setInnerBottomSkip(int bottomSkip);
|
void setInnerBottomSkip(int bottomSkip);
|
||||||
|
|
||||||
|
|
|
@ -18,6 +18,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||||
#include "ui/widgets/checkbox.h"
|
#include "ui/widgets/checkbox.h"
|
||||||
#include "ui/widgets/buttons.h"
|
#include "ui/widgets/buttons.h"
|
||||||
#include "ui/widgets/labels.h"
|
#include "ui/widgets/labels.h"
|
||||||
|
#include "ui/wrap/vertical_layout.h"
|
||||||
#include "ui/toast/toast.h"
|
#include "ui/toast/toast.h"
|
||||||
#include "ui/image/image.h"
|
#include "ui/image/image.h"
|
||||||
#include "ui/empty_userpic.h"
|
#include "ui/empty_userpic.h"
|
||||||
|
@ -803,3 +804,51 @@ void ConfirmInviteBox::paintEvent(QPaintEvent *e) {
|
||||||
}
|
}
|
||||||
|
|
||||||
ConfirmInviteBox::~ConfirmInviteBox() = default;
|
ConfirmInviteBox::~ConfirmInviteBox() = default;
|
||||||
|
|
||||||
|
ConfirmDontWarnBox::ConfirmDontWarnBox(
|
||||||
|
QWidget*,
|
||||||
|
const QString &text,
|
||||||
|
const QString &checkbox,
|
||||||
|
const QString &confirm,
|
||||||
|
FnMut<void(bool)> callback)
|
||||||
|
: _confirm(confirm)
|
||||||
|
, _content(setupContent(text, checkbox, std::move(callback))) {
|
||||||
|
}
|
||||||
|
|
||||||
|
void ConfirmDontWarnBox::prepare() {
|
||||||
|
setDimensionsToContent(st::boxWidth, _content);
|
||||||
|
addButton([=] { return _confirm; }, [=] { _callback(); });
|
||||||
|
addButton(langFactory(lng_cancel), [=] { closeBox(); });
|
||||||
|
}
|
||||||
|
|
||||||
|
not_null<Ui::RpWidget*> ConfirmDontWarnBox::setupContent(
|
||||||
|
const QString &text,
|
||||||
|
const QString &checkbox,
|
||||||
|
FnMut<void(bool)> callback) {
|
||||||
|
const auto result = Ui::CreateChild<Ui::VerticalLayout>(this);
|
||||||
|
result->add(
|
||||||
|
object_ptr<Ui::FlatLabel>(
|
||||||
|
result,
|
||||||
|
text,
|
||||||
|
Ui::FlatLabel::InitType::Rich,
|
||||||
|
st::boxLabel),
|
||||||
|
st::boxPadding);
|
||||||
|
const auto control = result->add(
|
||||||
|
object_ptr<Ui::Checkbox>(
|
||||||
|
result,
|
||||||
|
checkbox,
|
||||||
|
false,
|
||||||
|
st::defaultBoxCheckbox),
|
||||||
|
style::margins(
|
||||||
|
st::boxPadding.left(),
|
||||||
|
st::boxPadding.bottom(),
|
||||||
|
st::boxPadding.right(),
|
||||||
|
st::boxPadding.bottom()));
|
||||||
|
_callback = [=, callback = std::move(callback)]() mutable {
|
||||||
|
const auto checked = control->checked();
|
||||||
|
auto local = std::move(callback);
|
||||||
|
closeBox();
|
||||||
|
local(checked);
|
||||||
|
};
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
|
@ -232,3 +232,27 @@ private:
|
||||||
int _userWidth = 0;
|
int _userWidth = 0;
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
class ConfirmDontWarnBox : public BoxContent {
|
||||||
|
public:
|
||||||
|
ConfirmDontWarnBox(
|
||||||
|
QWidget*,
|
||||||
|
const QString &text,
|
||||||
|
const QString &checkbox,
|
||||||
|
const QString &confirm,
|
||||||
|
FnMut<void(bool)> callback);
|
||||||
|
|
||||||
|
protected:
|
||||||
|
void prepare() override;
|
||||||
|
|
||||||
|
private:
|
||||||
|
not_null<Ui::RpWidget*> setupContent(
|
||||||
|
const QString &text,
|
||||||
|
const QString &checkbox,
|
||||||
|
FnMut<void(bool)> callback);
|
||||||
|
|
||||||
|
QString _confirm;
|
||||||
|
FnMut<void()> _callback;
|
||||||
|
not_null<Ui::RpWidget*> _content;
|
||||||
|
|
||||||
|
};
|
||||||
|
|
|
@ -718,11 +718,7 @@ void ProxyBox::prepare() {
|
||||||
setTitle(langFactory(lng_proxy_edit));
|
setTitle(langFactory(lng_proxy_edit));
|
||||||
|
|
||||||
refreshButtons();
|
refreshButtons();
|
||||||
|
setDimensionsToContent(st::boxWideWidth, _content);
|
||||||
_content->heightValue(
|
|
||||||
) | rpl::start_with_next([=](int height) {
|
|
||||||
setDimensions(st::boxWideWidth, height);
|
|
||||||
}, _content->lifetime());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void ProxyBox::refreshButtons() {
|
void ProxyBox::refreshButtons() {
|
||||||
|
@ -905,8 +901,6 @@ void ProxyBox::setupControls(const ProxyData &data) {
|
||||||
setupCredentials(data);
|
setupCredentials(data);
|
||||||
setupMtprotoCredentials(data);
|
setupMtprotoCredentials(data);
|
||||||
|
|
||||||
_content->resizeToWidth(st::boxWideWidth);
|
|
||||||
|
|
||||||
const auto handleType = [=](Type type) {
|
const auto handleType = [=](Type type) {
|
||||||
_credentials->toggle(
|
_credentials->toggle(
|
||||||
type == Type::Http || type == Type::Socks5,
|
type == Type::Http || type == Type::Socks5,
|
||||||
|
@ -1032,15 +1026,7 @@ void AutoDownloadBox::setupContent() {
|
||||||
});
|
});
|
||||||
addButton(langFactory(lng_cancel), [=] { closeBox(); });
|
addButton(langFactory(lng_cancel), [=] { closeBox(); });
|
||||||
|
|
||||||
widthValue(
|
setDimensionsToContent(st::boxWideWidth, content);
|
||||||
) | rpl::start_with_next([=](int width) {
|
|
||||||
content->resizeToWidth(width);
|
|
||||||
}, content->lifetime());
|
|
||||||
|
|
||||||
content->heightValue(
|
|
||||||
) | rpl::start_with_next([=](int height) {
|
|
||||||
setDimensions(st::boxWideWidth, height);
|
|
||||||
}, content->lifetime());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ProxiesBoxController::ProxiesBoxController()
|
ProxiesBoxController::ProxiesBoxController()
|
||||||
|
|
|
@ -221,8 +221,6 @@ object_ptr<Ui::VerticalLayout> Controller::createContent() {
|
||||||
_wrap->add(createUpgradeButton());
|
_wrap->add(createUpgradeButton());
|
||||||
_wrap->add(createDeleteButton());
|
_wrap->add(createDeleteButton());
|
||||||
|
|
||||||
_wrap->resizeToWidth(st::boxWideWidth);
|
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1451,10 +1449,7 @@ void EditPeerInfoBox::prepare() {
|
||||||
[=] { controller->setFocus(); },
|
[=] { controller->setFocus(); },
|
||||||
lifetime());
|
lifetime());
|
||||||
auto content = controller->createContent();
|
auto content = controller->createContent();
|
||||||
content->heightValue(
|
setDimensionsToContent(st::boxWideWidth, content);
|
||||||
) | rpl::start_with_next([this](int height) {
|
|
||||||
setDimensions(st::boxWideWidth, height);
|
|
||||||
}, content->lifetime());
|
|
||||||
setInnerWidget(object_ptr<Ui::OverrideMargins>(
|
setInnerWidget(object_ptr<Ui::OverrideMargins>(
|
||||||
this,
|
this,
|
||||||
std::move(content)));
|
std::move(content)));
|
||||||
|
|
|
@ -218,14 +218,7 @@ void ManagePeerBox::prepare() {
|
||||||
}
|
}
|
||||||
|
|
||||||
void ManagePeerBox::setupContent() {
|
void ManagePeerBox::setupContent() {
|
||||||
auto content = Ui::CreateChild<Ui::VerticalLayout>(this);
|
const auto content = Ui::CreateChild<Ui::VerticalLayout>(this);
|
||||||
FillManageBox(App::wnd()->controller(), _channel, content);
|
FillManageBox(App::wnd()->controller(), _channel, content);
|
||||||
widthValue(
|
setDimensionsToContent(st::boxWidth, content);
|
||||||
) | rpl::start_with_next([=](int width) {
|
|
||||||
content->resizeToWidth(width);
|
|
||||||
}, content->lifetime());
|
|
||||||
content->heightValue(
|
|
||||||
) | rpl::start_with_next([=](int height) {
|
|
||||||
setDimensions(st::boxWidth, height);
|
|
||||||
}, content->lifetime());
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -23,6 +23,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||||
#include "history/history_media_types.h"
|
#include "history/history_media_types.h"
|
||||||
#include "window/window_controller.h"
|
#include "window/window_controller.h"
|
||||||
#include "storage/cache/storage_cache_database.h"
|
#include "storage/cache/storage_cache_database.h"
|
||||||
|
#include "boxes/confirm_box.h"
|
||||||
#include "ui/image/image.h"
|
#include "ui/image/image.h"
|
||||||
#include "ui/image/image_source.h"
|
#include "ui/image/image_source.h"
|
||||||
#include "auth_session.h"
|
#include "auth_session.h"
|
||||||
|
@ -65,6 +66,29 @@ QString JoinStringList(const QStringList &list, const QString &separator) {
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void LaunchWithWarning(const QString &name) {
|
||||||
|
if (!Data::IsExecutableName(name)
|
||||||
|
|| !Auth().settings().exeLaunchWarning()) {
|
||||||
|
File::Launch(name);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const auto extension = '.' + Data::FileExtension(name);
|
||||||
|
const auto callback = [=](bool checked) {
|
||||||
|
if (checked) {
|
||||||
|
Auth().settings().setExeLaunchWarning(false);
|
||||||
|
Auth().saveSettingsDelayed();
|
||||||
|
}
|
||||||
|
File::Launch(name);
|
||||||
|
};
|
||||||
|
Ui::show(Box<ConfirmDontWarnBox>(
|
||||||
|
lng_launch_exe_warning(
|
||||||
|
lt_extension,
|
||||||
|
textcmdStartSemibold() + extension + textcmdStopSemibold()),
|
||||||
|
lang(lng_launch_exe_dont_ask),
|
||||||
|
lang(lng_launch_exe_sure),
|
||||||
|
callback));
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
||||||
bool fileIsImage(const QString &name, const QString &mime) {
|
bool fileIsImage(const QString &name, const QString &mime) {
|
||||||
|
@ -308,15 +332,15 @@ void DocumentOpenClickHandler::Open(
|
||||||
Messenger::Instance().showDocument(data, context);
|
Messenger::Instance().showDocument(data, context);
|
||||||
location.accessDisable();
|
location.accessDisable();
|
||||||
} else {
|
} else {
|
||||||
auto filepath = location.name();
|
const auto filepath = location.name();
|
||||||
if (documentIsValidMediaFile(filepath)) {
|
if (Data::IsValidMediaFile(filepath)) {
|
||||||
File::Launch(filepath);
|
File::Launch(filepath);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
data->session()->data().markMediaRead(data);
|
data->session()->data().markMediaRead(data);
|
||||||
} else if (data->isVoiceMessage() || data->isAudioFile() || data->isVideoFile()) {
|
} else if (data->isVoiceMessage() || data->isAudioFile() || data->isVideoFile()) {
|
||||||
auto filepath = location.name();
|
const auto filepath = location.name();
|
||||||
if (documentIsValidMediaFile(filepath)) {
|
if (Data::IsValidMediaFile(filepath)) {
|
||||||
File::Launch(filepath);
|
File::Launch(filepath);
|
||||||
}
|
}
|
||||||
data->session()->data().markMediaRead(data);
|
data->session()->data().markMediaRead(data);
|
||||||
|
@ -335,14 +359,14 @@ void DocumentOpenClickHandler::Open(
|
||||||
Messenger::Instance().showDocument(data, context);
|
Messenger::Instance().showDocument(data, context);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
File::Launch(location.name());
|
LaunchWithWarning(location.name());
|
||||||
}
|
}
|
||||||
location.accessDisable();
|
location.accessDisable();
|
||||||
} else {
|
} else {
|
||||||
File::Launch(location.name());
|
LaunchWithWarning(location.name());
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
File::Launch(location.name());
|
LaunchWithWarning(location.name());
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -703,7 +727,7 @@ void DocumentData::performActionOnLoad() {
|
||||||
File::OpenWith(already, QCursor::pos());
|
File::OpenWith(already, QCursor::pos());
|
||||||
} else if (_actionOnLoad == ActionOnLoadOpen || _actionOnLoad == ActionOnLoadPlayInline) {
|
} else if (_actionOnLoad == ActionOnLoadOpen || _actionOnLoad == ActionOnLoadPlayInline) {
|
||||||
if (isVoiceMessage() || isAudioFile() || isVideoFile()) {
|
if (isVoiceMessage() || isAudioFile() || isVideoFile()) {
|
||||||
if (documentIsValidMediaFile(already)) {
|
if (Data::IsValidMediaFile(already)) {
|
||||||
File::Launch(already);
|
File::Launch(already);
|
||||||
}
|
}
|
||||||
_session->data().markMediaRead(this);
|
_session->data().markMediaRead(this);
|
||||||
|
@ -711,11 +735,11 @@ void DocumentData::performActionOnLoad() {
|
||||||
if (showImage && QImageReader(loc.name()).canRead()) {
|
if (showImage && QImageReader(loc.name()).canRead()) {
|
||||||
Messenger::Instance().showDocument(this, item);
|
Messenger::Instance().showDocument(this, item);
|
||||||
} else {
|
} else {
|
||||||
File::Launch(already);
|
LaunchWithWarning(already);
|
||||||
}
|
}
|
||||||
loc.accessDisable();
|
loc.accessDisable();
|
||||||
} else {
|
} else {
|
||||||
File::Launch(already);
|
LaunchWithWarning(already);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1405,3 +1429,57 @@ QString DocumentData::ComposeNameString(
|
||||||
auto trackTitle = (songTitle.isEmpty() ? qsl("Unknown Track") : songTitle);
|
auto trackTitle = (songTitle.isEmpty() ? qsl("Unknown Track") : songTitle);
|
||||||
return songPerformer + QString::fromUtf8(" \xe2\x80\x93 ") + trackTitle;
|
return songPerformer + QString::fromUtf8(" \xe2\x80\x93 ") + trackTitle;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
namespace Data {
|
||||||
|
|
||||||
|
QString FileExtension(const QString &filepath) {
|
||||||
|
const auto reversed = ranges::view::reverse(filepath);
|
||||||
|
const auto last = ranges::find_first_of(reversed, ".\\/");
|
||||||
|
if (last == reversed.end() || *last != '.') {
|
||||||
|
return QString();
|
||||||
|
}
|
||||||
|
return QString(last.base(), last - reversed.begin());
|
||||||
|
}
|
||||||
|
|
||||||
|
bool IsValidMediaFile(const QString &filepath) {
|
||||||
|
static const auto kExtensions = [] {
|
||||||
|
const auto list = qsl("\
|
||||||
|
webm mkv flv vob ogv ogg drc gif gifv mng avi mov qt wmv yuv rm rmvb asf \
|
||||||
|
amv mp4 m4p m4v mpg mp2 mpeg mpe mpv m2v svi 3gp 3g2 mxf roq nsv f4v f4p \
|
||||||
|
f4a f4b wma divx evo mk3d mka mks mcf m2p ps ts m2ts ifo aaf avchd cam dat \
|
||||||
|
dsh dvr-ms m1v fla flr sol wrap smi swf wtv 8svx 16svx iff aiff aif aifc \
|
||||||
|
au bwf cdda raw wav flac la pac m4a ape ofr ofs off rka shn tak tta wv \
|
||||||
|
brstm dts dtshd dtsma ast amr mp3 spx gsm aac mpc vqf ra ots swa vox voc \
|
||||||
|
dwd smp aup cust mid mus sib sid ly gym vgm psf nsf mod ptb s3m xm it mt2 \
|
||||||
|
minipsf psflib 2sf dsf gsf psf2 qsf ssf usf rmj spc niff mxl xml txm ym \
|
||||||
|
jam mp1 mscz").split(' ');
|
||||||
|
return base::flat_set<QString>(list.begin(), list.end());
|
||||||
|
}();
|
||||||
|
|
||||||
|
return ranges::binary_search(
|
||||||
|
kExtensions,
|
||||||
|
FileExtension(filepath).toLower());
|
||||||
|
}
|
||||||
|
|
||||||
|
bool IsExecutableName(const QString &filepath) {
|
||||||
|
static const auto kExtensions = [] {
|
||||||
|
const auto joined =
|
||||||
|
#ifdef Q_OS_MAC
|
||||||
|
qsl("action app bin command csh osx workflow");
|
||||||
|
#elif defined Q_OS_LINUX // Q_OS_MAC
|
||||||
|
qsl("bin csh ksh out run");
|
||||||
|
#else // Q_OS_MAC || Q_OS_LINUX
|
||||||
|
qsl("\
|
||||||
|
bat bin cmd com cpl exe gadget inf ins inx isu job jse lnk msc msi msp mst \
|
||||||
|
paf pif ps1 reg rgs scr sct shb shs u3p vb vbe vbs vbscript ws wsf");
|
||||||
|
#endif // !Q_OS_MAC && !Q_OS_LINUX
|
||||||
|
const auto list = joined.split(' ');
|
||||||
|
return base::flat_set<QString>(list.begin(), list.end());
|
||||||
|
}();
|
||||||
|
|
||||||
|
return ranges::binary_search(
|
||||||
|
kExtensions,
|
||||||
|
FileExtension(filepath).toLower());
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace Data
|
||||||
|
|
|
@ -331,3 +331,11 @@ QString FileNameForSave(
|
||||||
QString name,
|
QString name,
|
||||||
bool savingAs,
|
bool savingAs,
|
||||||
const QDir &dir = QDir());
|
const QDir &dir = QDir());
|
||||||
|
|
||||||
|
namespace Data {
|
||||||
|
|
||||||
|
QString FileExtension(const QString &filepath);
|
||||||
|
bool IsValidMediaFile(const QString &filepath);
|
||||||
|
bool IsExecutableName(const QString &filepath);
|
||||||
|
|
||||||
|
} // namespace Data
|
||||||
|
|
|
@ -1349,10 +1349,10 @@ void HistoryDocument::createComponents(bool caption) {
|
||||||
} else {
|
} else {
|
||||||
mask |= HistoryDocumentNamed::Bit();
|
mask |= HistoryDocumentNamed::Bit();
|
||||||
if (!_data->isSong()
|
if (!_data->isSong()
|
||||||
&& !documentIsExecutableName(_data->filename())
|
|
||||||
&& !_data->thumb->isNull()
|
&& !_data->thumb->isNull()
|
||||||
&& _data->thumb->width()
|
&& _data->thumb->width()
|
||||||
&& _data->thumb->height()) {
|
&& _data->thumb->height()
|
||||||
|
&& !Data::IsExecutableName(_data->filename())) {
|
||||||
mask |= HistoryDocumentThumbed::Bit();
|
mask |= HistoryDocumentThumbed::Bit();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -179,50 +179,6 @@ RoundCorners documentCorners(int32 colorIndex) {
|
||||||
return RoundCorners(Doc1Corners + (colorIndex & 3));
|
return RoundCorners(Doc1Corners + (colorIndex & 3));
|
||||||
}
|
}
|
||||||
|
|
||||||
bool documentIsValidMediaFile(const QString &filepath) {
|
|
||||||
static StaticNeverFreedPointer<QList<QString>> validMediaTypes(([] {
|
|
||||||
std::unique_ptr<QList<QString>> result = std::make_unique<QList<QString>>();
|
|
||||||
*result = qsl("\
|
|
||||||
webm mkv flv vob ogv ogg drc gif gifv mng avi mov qt wmv yuv rm rmvb asf amv mp4 m4p \
|
|
||||||
m4v mpg mp2 mpeg mpe mpv m2v svi 3gp 3g2 mxf roq nsv f4v f4p f4a f4b wma divx evo mk3d \
|
|
||||||
mka mks mcf m2p ps ts m2ts ifo aaf avchd cam dat dsh dvr-ms m1v fla flr sol wrap smi swf \
|
|
||||||
wtv 8svx 16svx iff aiff aif aifc au bwf cdda raw wav flac la pac m4a ape ofr ofs off rka \
|
|
||||||
shn tak tta wv brstm dts dtshd dtsma ast amr mp3 spx gsm aac mpc vqf ra ots swa vox voc \
|
|
||||||
dwd smp aup cust mid mus sib sid ly gym vgm psf nsf mod ptb s3m xm it mt2 minipsf psflib \
|
|
||||||
2sf dsf gsf psf2 qsf ssf usf rmj spc niff mxl xml txm ym jam mp1 mscz\
|
|
||||||
").split(' ');
|
|
||||||
return result.release();
|
|
||||||
})());
|
|
||||||
|
|
||||||
QFileInfo info(filepath);
|
|
||||||
auto parts = info.fileName().split('.', QString::SkipEmptyParts);
|
|
||||||
return !parts.isEmpty() && (validMediaTypes->indexOf(parts.back().toLower()) >= 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool documentIsExecutableName(const QString &filename) {
|
|
||||||
static StaticNeverFreedPointer<QList<QString>> executableTypes(([] {
|
|
||||||
std::unique_ptr<QList<QString>> result = std::make_unique<QList<QString>>();
|
|
||||||
#ifdef Q_OS_MAC
|
|
||||||
*result = qsl("\
|
|
||||||
action app bin command csh osx workflow\
|
|
||||||
").split(' ');
|
|
||||||
#elif defined Q_OS_LINUX // Q_OS_MAC
|
|
||||||
*result = qsl("\
|
|
||||||
bin csh ksh out run\
|
|
||||||
").split(' ');
|
|
||||||
#else // Q_OS_MAC || Q_OS_LINUX
|
|
||||||
*result = qsl("\
|
|
||||||
bat bin cmd com cpl exe gadget inf ins inx isu job jse lnk msc msi \
|
|
||||||
msp mst paf pif ps1 reg rgs sct shb shs u3p vb vbe vbs vbscript ws wsf\
|
|
||||||
").split(' ');
|
|
||||||
#endif // !Q_OS_MAC && !Q_OS_LINUX
|
|
||||||
return result.release();
|
|
||||||
})());
|
|
||||||
|
|
||||||
auto lastDotIndex = filename.lastIndexOf('.');
|
|
||||||
return (lastDotIndex >= 0) && (executableTypes->indexOf(filename.mid(lastDotIndex + 1).toLower()) >= 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
[[nodiscard]] HistoryView::TextState LayoutItemBase::getState(
|
[[nodiscard]] HistoryView::TextState LayoutItemBase::getState(
|
||||||
QPoint point,
|
QPoint point,
|
||||||
StateRequest request) const {
|
StateRequest request) const {
|
||||||
|
|
|
@ -68,8 +68,6 @@ style::color documentDarkColor(int colorIndex);
|
||||||
style::color documentOverColor(int colorIndex);
|
style::color documentOverColor(int colorIndex);
|
||||||
style::color documentSelectedColor(int colorIndex);
|
style::color documentSelectedColor(int colorIndex);
|
||||||
RoundCorners documentCorners(int colorIndex);
|
RoundCorners documentCorners(int colorIndex);
|
||||||
bool documentIsValidMediaFile(const QString &filepath);
|
|
||||||
bool documentIsExecutableName(const QString &filename);
|
|
||||||
|
|
||||||
class PaintContextBase {
|
class PaintContextBase {
|
||||||
public:
|
public:
|
||||||
|
|
|
@ -1141,7 +1141,7 @@ void MainWidget::handleAudioUpdate(const AudioMsgId &audioId) {
|
||||||
|
|
||||||
auto filepath = document->filepath(DocumentData::FilePathResolveSaveFromData);
|
auto filepath = document->filepath(DocumentData::FilePathResolveSaveFromData);
|
||||||
if (!filepath.isEmpty()) {
|
if (!filepath.isEmpty()) {
|
||||||
if (documentIsValidMediaFile(filepath)) {
|
if (Data::IsValidMediaFile(filepath)) {
|
||||||
File::Launch(filepath);
|
File::Launch(filepath);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1183,7 +1183,7 @@ bool Document::withThumb() const {
|
||||||
&& !_data->thumb->isNull()
|
&& !_data->thumb->isNull()
|
||||||
&& _data->thumb->width()
|
&& _data->thumb->width()
|
||||||
&& _data->thumb->height()
|
&& _data->thumb->height()
|
||||||
&& !documentIsExecutableName(_data->filename());
|
&& !Data::IsExecutableName(_data->filename());
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Document::updateStatusText() {
|
bool Document::updateStatusText() {
|
||||||
|
|
Loading…
Reference in New Issue