mirror of
https://github.com/fergalmoran/flameshot.git
synced 2025-12-22 09:51:06 +00:00
* Fix OpenWith on Windows (#1309) * Clang-format and function name fix * Clang-format
This commit is contained in:
@@ -95,5 +95,9 @@
|
||||
<file>img/material/white/move_down.svg</file>
|
||||
<file>img/material/white/move_up.svg</file>
|
||||
<file>img/material/white/delete.svg</file>
|
||||
<file>img/material/black/apps.svg</file>
|
||||
<file>img/material/black/image.svg</file>
|
||||
<file>img/material/white/apps.svg</file>
|
||||
<file>img/material/white/image.svg</file>
|
||||
</qresource>
|
||||
</RCC>
|
||||
|
||||
1
data/img/material/black/apps.svg
Normal file
1
data/img/material/black/apps.svg
Normal file
@@ -0,0 +1 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" height="24px" viewBox="0 0 24 24" width="24px" fill="#000000"><path d="M0 0h24v24H0V0z" fill="none"/><path d="M4 8h4V4H4v4zm6 12h4v-4h-4v4zm-6 0h4v-4H4v4zm0-6h4v-4H4v4zm6 0h4v-4h-4v4zm6-10v4h4V4h-4zm-6 4h4V4h-4v4zm6 6h4v-4h-4v4zm0 6h4v-4h-4v4z"/></svg>
|
||||
|
After Width: | Height: | Size: 292 B |
1
data/img/material/black/image.svg
Normal file
1
data/img/material/black/image.svg
Normal file
@@ -0,0 +1 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" height="24px" viewBox="0 0 24 24" width="24px" fill="#000000"><path d="M0 0h24v24H0V0z" fill="none"/><path d="M21 19V5c0-1.1-.9-2-2-2H5c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h14c1.1 0 2-.9 2-2zM8.9 13.98l2.1 2.53 3.1-3.99c.2-.26.6-.26.8.01l3.51 4.68c.25.33.01.8-.4.8H6.02c-.42 0-.65-.48-.39-.81L8.12 14c.19-.26.57-.27.78-.02z"/></svg>
|
||||
|
After Width: | Height: | Size: 368 B |
1
data/img/material/white/apps.svg
Normal file
1
data/img/material/white/apps.svg
Normal file
@@ -0,0 +1 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" height="24px" viewBox="0 0 24 24" width="24px" fill="#FFFFFF"><path d="M0 0h24v24H0V0z" fill="none"/><path d="M4 8h4V4H4v4zm6 12h4v-4h-4v4zm-6 0h4v-4H4v4zm0-6h4v-4H4v4zm6 0h4v-4h-4v4zm6-10v4h4V4h-4zm-6 4h4V4h-4v4zm6 6h4v-4h-4v4zm0 6h4v-4h-4v4z"/></svg>
|
||||
|
After Width: | Height: | Size: 292 B |
1
data/img/material/white/image.svg
Normal file
1
data/img/material/white/image.svg
Normal file
@@ -0,0 +1 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" height="24px" viewBox="0 0 24 24" width="24px" fill="#FFFFFF"><path d="M0 0h24v24H0V0z" fill="none"/><path d="M21 19V5c0-1.1-.9-2-2-2H5c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h14c1.1 0 2-.9 2-2zM8.9 13.98l2.1 2.53 3.1-3.99c.2-.26.6-.26.8.01l3.51 4.68c.25.33.01.8-.4.8H6.02c-.42 0-.65-.48-.39-.81L8.12 14c.19-.26.57-.27.78-.02z"/></svg>
|
||||
|
After Width: | Height: | Size: 368 B |
@@ -18,10 +18,15 @@
|
||||
#include <QMessageBox>
|
||||
#include <QPixmap>
|
||||
#include <QProcess>
|
||||
#include <QStandardPaths>
|
||||
#include <QTabWidget>
|
||||
|
||||
namespace {
|
||||
|
||||
#if defined(Q_OS_WIN)
|
||||
QMap<QString, QString> catIconNames({ { "Graphics", "image.svg" },
|
||||
{ "Utility", "apps.svg" } });
|
||||
}
|
||||
#else
|
||||
QMap<QString, QString> catIconNames(
|
||||
{ { "Multimedia", "applications-multimedia" },
|
||||
{ "Development", "applications-development" },
|
||||
@@ -33,6 +38,7 @@ QMap<QString, QString> catIconNames(
|
||||
{ "System", "preferences-system" },
|
||||
{ "Utility", "applications-utilities" } });
|
||||
}
|
||||
#endif
|
||||
|
||||
AppLauncherWidget::AppLauncherWidget(const QPixmap& p, QWidget* parent)
|
||||
: QWidget(parent)
|
||||
@@ -44,6 +50,18 @@ AppLauncherWidget::AppLauncherWidget(const QPixmap& p, QWidget* parent)
|
||||
|
||||
m_keepOpen = ConfigHandler().keepOpenAppLauncher();
|
||||
|
||||
#if defined(Q_OS_WIN)
|
||||
QDir userAppsFolder(
|
||||
QStandardPaths::standardLocations(QStandardPaths::ApplicationsLocation)
|
||||
.at(0));
|
||||
m_parser.processDirectory(userAppsFolder);
|
||||
|
||||
QString dir(m_parser.getAllUsersStartMenuPath());
|
||||
if (!dir.isEmpty()) {
|
||||
QDir allUserAppsFolder(dir);
|
||||
m_parser.processDirectory(allUserAppsFolder);
|
||||
}
|
||||
#else
|
||||
QString dirLocal = QDir::homePath() + "/.local/share/applications/";
|
||||
QDir appsDirLocal(dirLocal);
|
||||
m_parser.processDirectory(appsDirLocal);
|
||||
@@ -51,6 +69,7 @@ AppLauncherWidget::AppLauncherWidget(const QPixmap& p, QWidget* parent)
|
||||
QString dir = QStringLiteral("/usr/share/applications/");
|
||||
QDir appsDir(dir);
|
||||
m_parser.processDirectory(appsDir);
|
||||
#endif
|
||||
|
||||
initAppMap();
|
||||
initListWidget();
|
||||
@@ -99,7 +118,14 @@ void AppLauncherWidget::launch(const QModelIndex& index)
|
||||
// Heuristically, if there is a % in the command we assume it is the file
|
||||
// name slot
|
||||
QString command = index.data(Qt::UserRole).toString();
|
||||
#if defined(Q_OS_WIN)
|
||||
// Do not split on Windows, since file path can contain spaces
|
||||
// and % is not used in lnk files
|
||||
QStringList prog_args;
|
||||
prog_args << command;
|
||||
#else
|
||||
QStringList prog_args = command.split(" ");
|
||||
#endif
|
||||
// no quotes because it is going in an array!
|
||||
if (command.contains("%")) {
|
||||
// but that means we need to substitute IN the array not the string!
|
||||
@@ -121,8 +147,10 @@ void AppLauncherWidget::launch(const QModelIndex& index)
|
||||
this, tr("Error"), tr("Unable to launch in terminal."));
|
||||
}
|
||||
} else {
|
||||
QFileInfo fi(m_tempFile);
|
||||
QString workingDir = fi.absolutePath();
|
||||
prog_args.removeAt(0); // strip program name out
|
||||
QProcess::startDetached(app_name, prog_args);
|
||||
QProcess::startDetached(app_name, prog_args, workingDir);
|
||||
}
|
||||
if (!m_keepOpen) {
|
||||
close();
|
||||
@@ -185,8 +213,17 @@ void AppLauncherWidget::initListWidget()
|
||||
const QVector<DesktopAppData>& appList = m_appsMap[cat];
|
||||
addAppsToListWidget(itemsWidget, appList);
|
||||
|
||||
#if defined(Q_OS_WIN)
|
||||
QColor background = this->palette().window().color();
|
||||
bool isDark = ColorUtils::colorIsDark(background);
|
||||
QString modifier =
|
||||
isDark ? PathInfo::whiteIconPath() : PathInfo::blackIconPath();
|
||||
m_tabWidget->addTab(
|
||||
itemsWidget, QIcon(modifier + iconName), QLatin1String(""));
|
||||
#else
|
||||
m_tabWidget->addTab(
|
||||
itemsWidget, QIcon::fromTheme(iconName), QLatin1String(""));
|
||||
#endif
|
||||
m_tabWidget->setTabToolTip(m_tabWidget->count(), cat);
|
||||
if (cat == QLatin1String("Graphics")) {
|
||||
m_tabWidget->setCurrentIndex(m_tabWidget->count() - 1);
|
||||
@@ -215,18 +252,21 @@ void AppLauncherWidget::initAppMap()
|
||||
QStringList multimediaNames;
|
||||
multimediaNames << QStringLiteral("AudioVideo") << QStringLiteral("Audio")
|
||||
<< QStringLiteral("Video");
|
||||
for (const QString& name : multimediaNames) {
|
||||
for (const QString& name : qAsConst(multimediaNames)) {
|
||||
if (!m_appsMap.contains(name)) {
|
||||
continue;
|
||||
}
|
||||
for (auto i : m_appsMap[name]) {
|
||||
for (const auto& i : m_appsMap[name]) {
|
||||
if (!multimediaList.contains(i)) {
|
||||
multimediaList.append(i);
|
||||
}
|
||||
}
|
||||
m_appsMap.remove(name);
|
||||
}
|
||||
m_appsMap.insert(QStringLiteral("Multimedia"), multimediaList);
|
||||
|
||||
if (!multimediaList.isEmpty()) {
|
||||
m_appsMap.insert(QStringLiteral("Multimedia"), multimediaList);
|
||||
}
|
||||
}
|
||||
|
||||
void AppLauncherWidget::configureListView(QListWidget* widget)
|
||||
|
||||
@@ -3,10 +3,15 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "src/utils/desktopfileparse.h"
|
||||
#include <QMap>
|
||||
#include <QWidget>
|
||||
|
||||
#if defined(Q_OS_WIN)
|
||||
#include "src/utils/winlnkfileparse.h"
|
||||
#else
|
||||
#include "src/utils/desktopfileparse.h"
|
||||
#endif
|
||||
|
||||
class QTabWidget;
|
||||
class QCheckBox;
|
||||
class QVBoxLayout;
|
||||
@@ -32,7 +37,11 @@ private:
|
||||
const QVector<DesktopAppData>& appList);
|
||||
void keyPressEvent(QKeyEvent* keyEvent) override;
|
||||
|
||||
#if defined(Q_OS_WIN)
|
||||
WinLnkFileParser m_parser;
|
||||
#else
|
||||
DesktopFileParser m_parser;
|
||||
#endif
|
||||
QPixmap m_pixmap;
|
||||
QString m_tempFile;
|
||||
bool m_keepOpen;
|
||||
|
||||
@@ -26,5 +26,12 @@ target_sources(
|
||||
colorutils.cpp
|
||||
history.cpp
|
||||
strfparse.cpp
|
||||
request.cpp
|
||||
request.cpp
|
||||
)
|
||||
|
||||
IF (WIN32)
|
||||
target_sources(
|
||||
flameshot
|
||||
PRIVATE winlnkfileparse.cpp
|
||||
)
|
||||
ENDIF()
|
||||
|
||||
@@ -114,7 +114,7 @@ int DesktopFileParser::processDirectory(const QDir& dir)
|
||||
dir.entryList({ "*.desktop" }, QDir::NoDotAndDotDot | QDir::Files);
|
||||
bool ok;
|
||||
int length = m_appList.length();
|
||||
for (QString file : entries) {
|
||||
for (const QString& file : entries) {
|
||||
DesktopAppData app = parseDesktopFile(dir.absoluteFilePath(file), ok);
|
||||
if (ok) {
|
||||
m_appList.append(app);
|
||||
@@ -127,7 +127,7 @@ QVector<DesktopAppData> DesktopFileParser::getAppsByCategory(
|
||||
const QString& category)
|
||||
{
|
||||
QVector<DesktopAppData> res;
|
||||
for (const DesktopAppData& app : m_appList) {
|
||||
for (const DesktopAppData& app : qAsConst(m_appList)) {
|
||||
if (app.categories.contains(category)) {
|
||||
res.append(app);
|
||||
}
|
||||
@@ -139,7 +139,7 @@ QMap<QString, QVector<DesktopAppData>> DesktopFileParser::getAppsByCategory(
|
||||
const QStringList& categories)
|
||||
{
|
||||
QMap<QString, QVector<DesktopAppData>> res;
|
||||
for (const DesktopAppData& app : m_appList) {
|
||||
for (const DesktopAppData& app : qAsConst(m_appList)) {
|
||||
for (const QString& category : categories) {
|
||||
if (app.categories.contains(category)) {
|
||||
res[category].append(app);
|
||||
|
||||
160
src/utils/winlnkfileparse.cpp
Normal file
160
src/utils/winlnkfileparse.cpp
Normal file
@@ -0,0 +1,160 @@
|
||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||
// SPDX-FileCopyrightText: 2017-2019 Alejandro Sirgo Rica & Contributors
|
||||
|
||||
#include "winlnkfileparse.h"
|
||||
#include <QDir>
|
||||
#include <QDirIterator>
|
||||
#include <QFileSystemModel>
|
||||
#include <QImageWriter>
|
||||
#include <QRegularExpression>
|
||||
#include <QSettings>
|
||||
#include <QString>
|
||||
|
||||
#include <shlobj.h>
|
||||
|
||||
WinLnkFileParser::WinLnkFileParser()
|
||||
{
|
||||
QStringList sListImgFileExt;
|
||||
for (const auto& ext : QImageWriter::supportedImageFormats()) {
|
||||
sListImgFileExt.append(ext);
|
||||
}
|
||||
this->getImageFileExtAssociates(sListImgFileExt);
|
||||
}
|
||||
|
||||
DesktopAppData WinLnkFileParser::parseLnkFile(const QFileInfo& fiLnk,
|
||||
bool& ok) const
|
||||
{
|
||||
DesktopAppData res;
|
||||
ok = true;
|
||||
|
||||
QFileInfo fiSymlink(fiLnk.symLinkTarget());
|
||||
if (!fiSymlink.exists() || !fiSymlink.fileName().endsWith(".exe") ||
|
||||
fiSymlink.baseName().contains("unins")) {
|
||||
ok = false;
|
||||
return res;
|
||||
}
|
||||
|
||||
res.name = fiLnk.baseName();
|
||||
res.exec = fiSymlink.absoluteFilePath();
|
||||
|
||||
// Get icon from exe
|
||||
QFileSystemModel* model = new QFileSystemModel;
|
||||
model->setRootPath(fiSymlink.path());
|
||||
res.icon = model->fileIcon(model->index(fiSymlink.filePath()));
|
||||
|
||||
if (m_GraphicAppsList.contains(fiSymlink.fileName())) {
|
||||
res.categories = QStringList() << "Graphics";
|
||||
} else {
|
||||
res.categories = QStringList() << "Utility";
|
||||
}
|
||||
|
||||
for (const auto& app : m_appList) {
|
||||
if (app.exec == res.exec) {
|
||||
ok = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (res.exec.isEmpty() || res.name.isEmpty()) {
|
||||
ok = false;
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
int WinLnkFileParser::processDirectory(const QDir& dir)
|
||||
{
|
||||
QStringList sListMenuFilter;
|
||||
sListMenuFilter << "Accessibility"
|
||||
<< "Administrative Tools"
|
||||
<< "Setup"
|
||||
<< "System Tools"
|
||||
<< "Uninstall"
|
||||
<< "Update"
|
||||
<< "Updater"
|
||||
<< "Windows PowerShell";
|
||||
const QString sMenuFilter("\\b(" + sListMenuFilter.join('|') + ")\\b");
|
||||
QRegularExpression regexfilter(sMenuFilter);
|
||||
|
||||
bool ok;
|
||||
int length = m_appList.length();
|
||||
// Go through all subfolders and *.lnk files
|
||||
QDirIterator it(dir.absolutePath(),
|
||||
{ "*.lnk" },
|
||||
QDir::NoFilter,
|
||||
QDirIterator::Subdirectories);
|
||||
while (it.hasNext()) {
|
||||
QFileInfo fiLnk(it.next());
|
||||
if (!regexfilter.match(fiLnk.absoluteFilePath()).hasMatch()) {
|
||||
DesktopAppData app = parseLnkFile(fiLnk, ok);
|
||||
if (ok) {
|
||||
m_appList.append(app);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return m_appList.length() - length;
|
||||
}
|
||||
|
||||
QVector<DesktopAppData> WinLnkFileParser::getAppsByCategory(
|
||||
const QString& category)
|
||||
{
|
||||
QVector<DesktopAppData> res;
|
||||
for (const DesktopAppData& app : qAsConst(m_appList)) {
|
||||
if (app.categories.contains(category)) {
|
||||
res.append(app);
|
||||
}
|
||||
}
|
||||
|
||||
std::sort(res.begin(), res.end(), CompareAppByName());
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
QMap<QString, QVector<DesktopAppData>> WinLnkFileParser::getAppsByCategory(
|
||||
const QStringList& categories)
|
||||
{
|
||||
QMap<QString, QVector<DesktopAppData>> res;
|
||||
|
||||
QVector<DesktopAppData> tmpAppList;
|
||||
for (const QString& category : categories) {
|
||||
tmpAppList = getAppsByCategory(category);
|
||||
for (const DesktopAppData& app : qAsConst(tmpAppList)) {
|
||||
res[category].append(app);
|
||||
}
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
QString WinLnkFileParser::getAllUsersStartMenuPath()
|
||||
{
|
||||
QString sRet("");
|
||||
WCHAR path[MAX_PATH];
|
||||
HRESULT hr = SHGetFolderPathW(NULL, CSIDL_COMMON_PROGRAMS, NULL, 0, path);
|
||||
|
||||
if (SUCCEEDED(hr)) {
|
||||
sRet = QDir(QString::fromWCharArray(path)).absolutePath();
|
||||
}
|
||||
|
||||
return sRet;
|
||||
}
|
||||
|
||||
void WinLnkFileParser::getImageFileExtAssociates(const QStringList& sListImgExt)
|
||||
{
|
||||
const QString sReg("HKEY_CURRENT_USER\\SOFTWARE\\Microsoft\\Windows\\"
|
||||
"CurrentVersion\\Explorer\\FileExts\\.%1\\OpenWithList");
|
||||
|
||||
for (const auto& sExt : qAsConst(sListImgExt)) {
|
||||
QString sPath(sReg.arg(sExt));
|
||||
QSettings registry(sPath, QSettings::NativeFormat);
|
||||
for (const auto& key : registry.allKeys()) {
|
||||
if (1 == key.size()) { // Keys for OpenWith apps are a, b, c, ...
|
||||
QString sVal = registry.value(key, "").toString();
|
||||
if (sVal.endsWith(".exe") &&
|
||||
!m_GraphicAppsList.contains(sVal)) {
|
||||
m_GraphicAppsList << sVal;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
39
src/utils/winlnkfileparse.h
Normal file
39
src/utils/winlnkfileparse.h
Normal file
@@ -0,0 +1,39 @@
|
||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||
// SPDX-FileCopyrightText: 2017-2019 Alejandro Sirgo Rica & Contributors
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "desktopfileparse.h"
|
||||
#include <QFileInfo>
|
||||
#include <QIcon>
|
||||
#include <QMap>
|
||||
#include <QStringList>
|
||||
|
||||
class QDir;
|
||||
class QString;
|
||||
|
||||
struct CompareAppByName
|
||||
{
|
||||
bool operator()(const DesktopAppData a, const DesktopAppData b)
|
||||
{
|
||||
return (a.name < b.name);
|
||||
}
|
||||
};
|
||||
|
||||
struct WinLnkFileParser
|
||||
{
|
||||
WinLnkFileParser();
|
||||
DesktopAppData parseLnkFile(const QFileInfo& fiLnk, bool& ok) const;
|
||||
int processDirectory(const QDir& dir);
|
||||
QString getAllUsersStartMenuPath();
|
||||
|
||||
QVector<DesktopAppData> getAppsByCategory(const QString& category);
|
||||
QMap<QString, QVector<DesktopAppData>> getAppsByCategory(
|
||||
const QStringList& categories);
|
||||
|
||||
private:
|
||||
void getImageFileExtAssociates(const QStringList& sListImgExt);
|
||||
|
||||
QVector<DesktopAppData> m_appList;
|
||||
QStringList m_GraphicAppsList;
|
||||
};
|
||||
@@ -118,9 +118,12 @@ CaptureWidget::CaptureWidget(const CaptureRequest& req,
|
||||
m_context.origScreenshot = m_context.screenshot;
|
||||
|
||||
#if defined(Q_OS_WIN)
|
||||
// Call cmake with -DFLAMESHOT_DEBUG_CAPTURE=ON to enable easier debugging
|
||||
#if !defined(FLAMESHOT_DEBUG_CAPTURE)
|
||||
setWindowFlags(Qt::WindowStaysOnTopHint | Qt::FramelessWindowHint |
|
||||
Qt::SubWindow // Hides the taskbar icon
|
||||
);
|
||||
#endif
|
||||
|
||||
for (QScreen* const screen : QGuiApplication::screens()) {
|
||||
QPoint topLeftScreen = screen->geometry().topLeft();
|
||||
|
||||
Reference in New Issue
Block a user