mirror of
https://gitee.com/vnotex/vnote.git
synced 2025-07-05 05:49:53 +08:00
support file associations and open with built-in editors
This commit is contained in:
parent
737f9e51d8
commit
b3a385693c
@ -5,6 +5,8 @@
|
|||||||
|
|
||||||
#include <utils/fileutils.h>
|
#include <utils/fileutils.h>
|
||||||
#include "buffer.h"
|
#include "buffer.h"
|
||||||
|
#include <core/configmgr.h>
|
||||||
|
#include <core/coreconfig.h>
|
||||||
|
|
||||||
using namespace vnotex;
|
using namespace vnotex;
|
||||||
|
|
||||||
@ -20,24 +22,38 @@ bool FileType::isMarkdown() const
|
|||||||
|
|
||||||
FileTypeHelper::FileTypeHelper()
|
FileTypeHelper::FileTypeHelper()
|
||||||
{
|
{
|
||||||
setupBuiltInTypes();
|
reload();
|
||||||
|
}
|
||||||
|
|
||||||
// TODO: read configuration file.
|
void FileTypeHelper::reload()
|
||||||
|
{
|
||||||
|
setupBuiltInTypes();
|
||||||
|
|
||||||
setupSuffixTypeMap();
|
setupSuffixTypeMap();
|
||||||
}
|
}
|
||||||
|
|
||||||
void FileTypeHelper::setupBuiltInTypes()
|
void FileTypeHelper::setupBuiltInTypes()
|
||||||
{
|
{
|
||||||
|
m_fileTypes.clear();
|
||||||
|
|
||||||
|
const auto &coreConfig = ConfigMgr::getInst().getCoreConfig();
|
||||||
|
|
||||||
{
|
{
|
||||||
FileType type;
|
FileType type;
|
||||||
type.m_type = FileType::Markdown;
|
type.m_type = FileType::Markdown;
|
||||||
type.m_displayName = Buffer::tr("Markdown");
|
|
||||||
type.m_typeName = QStringLiteral("Markdown");
|
type.m_typeName = QStringLiteral("Markdown");
|
||||||
|
type.m_displayName = Buffer::tr("Markdown");
|
||||||
|
|
||||||
|
auto suffixes = coreConfig.findFileTypeSuffix(type.m_typeName);
|
||||||
|
if (suffixes && !suffixes->isEmpty()) {
|
||||||
|
type.m_suffixes = *suffixes;
|
||||||
|
} else {
|
||||||
type.m_suffixes << QStringLiteral("md")
|
type.m_suffixes << QStringLiteral("md")
|
||||||
<< QStringLiteral("mkd")
|
<< QStringLiteral("mkd")
|
||||||
<< QStringLiteral("rmd")
|
<< QStringLiteral("rmd")
|
||||||
<< QStringLiteral("markdown");
|
<< QStringLiteral("markdown");
|
||||||
|
}
|
||||||
|
|
||||||
m_fileTypes.push_back(type);
|
m_fileTypes.push_back(type);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -46,7 +62,14 @@ void FileTypeHelper::setupBuiltInTypes()
|
|||||||
type.m_type = FileType::Text;
|
type.m_type = FileType::Text;
|
||||||
type.m_typeName = QStringLiteral("Text");
|
type.m_typeName = QStringLiteral("Text");
|
||||||
type.m_displayName = Buffer::tr("Text");
|
type.m_displayName = Buffer::tr("Text");
|
||||||
|
|
||||||
|
auto suffixes = coreConfig.findFileTypeSuffix(type.m_typeName);
|
||||||
|
if (suffixes && !suffixes->isEmpty()) {
|
||||||
|
type.m_suffixes = *suffixes;
|
||||||
|
} else {
|
||||||
type.m_suffixes << QStringLiteral("txt") << QStringLiteral("text") << QStringLiteral("log");
|
type.m_suffixes << QStringLiteral("txt") << QStringLiteral("text") << QStringLiteral("log");
|
||||||
|
}
|
||||||
|
|
||||||
m_fileTypes.push_back(type);
|
m_fileTypes.push_back(type);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -88,10 +111,10 @@ const FileType &FileTypeHelper::getFileTypeBySuffix(const QString &p_suffix) con
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#define ADD(x, y) m_suffixTypeMap.insert((x), (y))
|
|
||||||
|
|
||||||
void FileTypeHelper::setupSuffixTypeMap()
|
void FileTypeHelper::setupSuffixTypeMap()
|
||||||
{
|
{
|
||||||
|
m_suffixTypeMap.clear();
|
||||||
|
|
||||||
for (int i = 0; i < m_fileTypes.size(); ++i) {
|
for (int i = 0; i < m_fileTypes.size(); ++i) {
|
||||||
for (const auto &suffix : m_fileTypes[i].m_suffixes) {
|
for (const auto &suffix : m_fileTypes[i].m_suffixes) {
|
||||||
if (m_suffixTypeMap.contains(suffix)) {
|
if (m_suffixTypeMap.contains(suffix)) {
|
||||||
@ -113,7 +136,7 @@ const FileType &FileTypeHelper::getFileType(int p_type) const
|
|||||||
return m_fileTypes[p_type];
|
return m_fileTypes[p_type];
|
||||||
}
|
}
|
||||||
|
|
||||||
const FileTypeHelper &FileTypeHelper::getInst()
|
FileTypeHelper &FileTypeHelper::getInst()
|
||||||
{
|
{
|
||||||
static FileTypeHelper helper;
|
static FileTypeHelper helper;
|
||||||
return helper;
|
return helper;
|
||||||
|
@ -32,6 +32,7 @@ namespace vnotex
|
|||||||
bool isMarkdown() const;
|
bool isMarkdown() const;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// Only handle built-in editors.
|
||||||
class FileTypeHelper
|
class FileTypeHelper
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
@ -47,7 +48,9 @@ namespace vnotex
|
|||||||
|
|
||||||
bool checkFileType(const QString &p_filePath, int p_type) const;
|
bool checkFileType(const QString &p_filePath, int p_type) const;
|
||||||
|
|
||||||
static const FileTypeHelper &getInst();
|
void reload();
|
||||||
|
|
||||||
|
static FileTypeHelper &getInst();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
FileTypeHelper();
|
FileTypeHelper();
|
||||||
|
@ -18,6 +18,8 @@ namespace vnotex
|
|||||||
|
|
||||||
virtual Buffer *createBuffer(const BufferParameters &p_parameters,
|
virtual Buffer *createBuffer(const BufferParameters &p_parameters,
|
||||||
QObject *p_parent) = 0;
|
QObject *p_parent) = 0;
|
||||||
|
|
||||||
|
virtual bool isBufferCreatedByFactory(const Buffer *p_buffer) const = 0;
|
||||||
};
|
};
|
||||||
} // ns vnotex
|
} // ns vnotex
|
||||||
|
|
||||||
|
@ -9,3 +9,8 @@ Buffer *MarkdownBufferFactory::createBuffer(const BufferParameters &p_parameters
|
|||||||
{
|
{
|
||||||
return new MarkdownBuffer(p_parameters, p_parent);
|
return new MarkdownBuffer(p_parameters, p_parent);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool MarkdownBufferFactory::isBufferCreatedByFactory(const Buffer *p_buffer) const
|
||||||
|
{
|
||||||
|
return dynamic_cast<const MarkdownBuffer *>(p_buffer) != nullptr;
|
||||||
|
}
|
||||||
|
@ -11,6 +11,8 @@ namespace vnotex
|
|||||||
public:
|
public:
|
||||||
Buffer *createBuffer(const BufferParameters &p_parameters,
|
Buffer *createBuffer(const BufferParameters &p_parameters,
|
||||||
QObject *p_parent) Q_DECL_OVERRIDE;
|
QObject *p_parent) Q_DECL_OVERRIDE;
|
||||||
|
|
||||||
|
bool isBufferCreatedByFactory(const Buffer *p_buffer) const Q_DECL_OVERRIDE;
|
||||||
};
|
};
|
||||||
} // vnotex
|
} // vnotex
|
||||||
|
|
||||||
|
@ -9,3 +9,8 @@ Buffer *TextBufferFactory::createBuffer(const BufferParameters &p_parameters,
|
|||||||
{
|
{
|
||||||
return new TextBuffer(p_parameters, p_parent);
|
return new TextBuffer(p_parameters, p_parent);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool TextBufferFactory::isBufferCreatedByFactory(const Buffer *p_buffer) const
|
||||||
|
{
|
||||||
|
return dynamic_cast<const TextBuffer *>(p_buffer) != nullptr;
|
||||||
|
}
|
||||||
|
@ -11,6 +11,8 @@ namespace vnotex
|
|||||||
public:
|
public:
|
||||||
Buffer *createBuffer(const BufferParameters &p_parameters,
|
Buffer *createBuffer(const BufferParameters &p_parameters,
|
||||||
QObject *p_parent) Q_DECL_OVERRIDE;
|
QObject *p_parent) Q_DECL_OVERRIDE;
|
||||||
|
|
||||||
|
bool isBufferCreatedByFactory(const Buffer *p_buffer) const Q_DECL_OVERRIDE;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -11,14 +11,19 @@
|
|||||||
#include <buffer/nodebufferprovider.h>
|
#include <buffer/nodebufferprovider.h>
|
||||||
#include <buffer/filebufferprovider.h>
|
#include <buffer/filebufferprovider.h>
|
||||||
#include <utils/widgetutils.h>
|
#include <utils/widgetutils.h>
|
||||||
|
#include <utils/processutils.h>
|
||||||
#include "notebookmgr.h"
|
#include "notebookmgr.h"
|
||||||
#include "vnotex.h"
|
#include "vnotex.h"
|
||||||
#include "externalfile.h"
|
#include "externalfile.h"
|
||||||
|
#include "sessionconfig.h"
|
||||||
|
#include "configmgr.h"
|
||||||
|
|
||||||
#include "fileopenparameters.h"
|
#include "fileopenparameters.h"
|
||||||
|
|
||||||
using namespace vnotex;
|
using namespace vnotex;
|
||||||
|
|
||||||
|
QMap<QString, QString> BufferMgr::s_suffixToFileType;
|
||||||
|
|
||||||
BufferMgr::BufferMgr(QObject *p_parent)
|
BufferMgr::BufferMgr(QObject *p_parent)
|
||||||
: QObject(p_parent)
|
: QObject(p_parent)
|
||||||
{
|
{
|
||||||
@ -66,12 +71,27 @@ void BufferMgr::open(Node *p_node, const QSharedPointer<FileOpenParameters> &p_p
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const auto nodePath = p_node->fetchAbsolutePath();
|
||||||
|
|
||||||
|
auto fileType = p_paras->m_fileType;
|
||||||
|
if (fileType.isEmpty()) {
|
||||||
|
// Check if we need to open it with external program by default according to the suffix.
|
||||||
|
fileType = findFileTypeByFile(nodePath);
|
||||||
|
if (openWithExternalProgram(nodePath, fileType)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
auto buffer = findBuffer(p_node);
|
auto buffer = findBuffer(p_node);
|
||||||
if (!buffer) {
|
if (!buffer || !isSameTypeBuffer(buffer, fileType)) {
|
||||||
auto nodePath = p_node->fetchAbsolutePath();
|
|
||||||
auto nodeFile = p_node->getContentFile();
|
auto nodeFile = p_node->getContentFile();
|
||||||
Q_ASSERT(nodeFile);
|
Q_ASSERT(nodeFile);
|
||||||
auto fileType = nodeFile->getContentType().m_typeName;
|
if (fileType.isEmpty()) {
|
||||||
|
fileType = nodeFile->getContentType().m_typeName;
|
||||||
|
} else if (fileType != nodeFile->getContentType().m_typeName) {
|
||||||
|
nodeFile->setContentType(FileTypeHelper::getInst().getFileTypeByName(fileType).m_type);
|
||||||
|
}
|
||||||
|
|
||||||
auto factory = m_bufferServer->getItem(fileType);
|
auto factory = m_bufferServer->getItem(fileType);
|
||||||
if (!factory) {
|
if (!factory) {
|
||||||
// No factory to open this file type.
|
// No factory to open this file type.
|
||||||
@ -96,6 +116,11 @@ void BufferMgr::open(const QString &p_filePath, const QSharedPointer<FileOpenPar
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Check if it is requested to open with external program.
|
||||||
|
if (openWithExternalProgram(p_filePath, p_paras->m_fileType)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
QFileInfo finfo(p_filePath);
|
QFileInfo finfo(p_filePath);
|
||||||
if (!finfo.exists()) {
|
if (!finfo.exists()) {
|
||||||
auto msg = QString("Failed to open file that does not exist (%1)").arg(p_filePath);
|
auto msg = QString("Failed to open file that does not exist (%1)").arg(p_filePath);
|
||||||
@ -123,11 +148,25 @@ void BufferMgr::open(const QString &p_filePath, const QSharedPointer<FileOpenPar
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
auto fileType = p_paras->m_fileType;
|
||||||
|
if (fileType.isEmpty()) {
|
||||||
|
// Check if we need to open it with external program by default according to the suffix.
|
||||||
|
fileType = findFileTypeByFile(p_filePath);
|
||||||
|
if (openWithExternalProgram(p_filePath, fileType)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
auto buffer = findBuffer(p_filePath);
|
auto buffer = findBuffer(p_filePath);
|
||||||
if (!buffer) {
|
if (!buffer || !isSameTypeBuffer(buffer, fileType)) {
|
||||||
// Open it as external file.
|
// Open it as external file.
|
||||||
auto externalFile = QSharedPointer<ExternalFile>::create(p_filePath);
|
auto externalFile = QSharedPointer<ExternalFile>::create(p_filePath);
|
||||||
auto fileType = externalFile->getContentType().m_typeName;
|
if (fileType.isEmpty()) {
|
||||||
|
fileType = externalFile->getContentType().m_typeName;
|
||||||
|
} else if (fileType != externalFile->getContentType().m_typeName) {
|
||||||
|
externalFile->setContentType(FileTypeHelper::getInst().getFileTypeByName(fileType).m_type);
|
||||||
|
}
|
||||||
|
|
||||||
auto factory = m_bufferServer->getItem(fileType);
|
auto factory = m_bufferServer->getItem(fileType);
|
||||||
if (!factory) {
|
if (!factory) {
|
||||||
// No factory to open this file type.
|
// No factory to open this file type.
|
||||||
@ -188,3 +227,64 @@ void BufferMgr::addBuffer(Buffer *p_buffer)
|
|||||||
p_buffer->deleteLater();
|
p_buffer->deleteLater();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool BufferMgr::openWithExternalProgram(const QString &p_filePath, const QString &p_name) const
|
||||||
|
{
|
||||||
|
if (p_name.isEmpty()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (auto pro = ConfigMgr::getInst().getSessionConfig().findExternalProgram(p_name)) {
|
||||||
|
const auto command = pro->fetchCommand(p_filePath);
|
||||||
|
if (!command.isEmpty()) {
|
||||||
|
ProcessUtils::startDetached(command);
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool BufferMgr::isSameTypeBuffer(const Buffer *p_buffer, const QString &p_typeName) const
|
||||||
|
{
|
||||||
|
if (p_typeName.isEmpty()) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto factory = m_bufferServer->getItem(p_typeName);
|
||||||
|
Q_ASSERT(factory);
|
||||||
|
if (factory) {
|
||||||
|
return factory->isBufferCreatedByFactory(p_buffer);
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void BufferMgr::updateSuffixToFileType(const QVector<CoreConfig::FileTypeSuffix> &p_fileTypeSuffixes)
|
||||||
|
{
|
||||||
|
s_suffixToFileType.clear();
|
||||||
|
|
||||||
|
for (const auto &fts : p_fileTypeSuffixes) {
|
||||||
|
for (const auto &suf : fts.m_suffixes) {
|
||||||
|
auto it = s_suffixToFileType.find(suf);
|
||||||
|
if (it != s_suffixToFileType.end()) {
|
||||||
|
qWarning() << "suffix conflicts for file types" << fts.m_name << it.value();
|
||||||
|
it.value() = fts.m_name;
|
||||||
|
} else {
|
||||||
|
s_suffixToFileType.insert(suf, fts.m_name);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
QString BufferMgr::findFileTypeByFile(const QString &p_filePath)
|
||||||
|
{
|
||||||
|
QFileInfo fi(p_filePath);
|
||||||
|
auto suffix = fi.suffix().toLower();
|
||||||
|
auto it = s_suffixToFileType.find(suffix);
|
||||||
|
if (it != s_suffixToFileType.end()) {
|
||||||
|
return it.value();
|
||||||
|
} else {
|
||||||
|
return QString();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -5,8 +5,10 @@
|
|||||||
#include <QScopedPointer>
|
#include <QScopedPointer>
|
||||||
#include <QSharedPointer>
|
#include <QSharedPointer>
|
||||||
#include <QVector>
|
#include <QVector>
|
||||||
|
#include <QMap>
|
||||||
|
|
||||||
#include "namebasedserver.h"
|
#include "namebasedserver.h"
|
||||||
|
#include "coreconfig.h"
|
||||||
|
|
||||||
namespace vnotex
|
namespace vnotex
|
||||||
{
|
{
|
||||||
@ -30,6 +32,8 @@ namespace vnotex
|
|||||||
|
|
||||||
void open(const QString &p_filePath, const QSharedPointer<FileOpenParameters> &p_paras);
|
void open(const QString &p_filePath, const QSharedPointer<FileOpenParameters> &p_paras);
|
||||||
|
|
||||||
|
static void updateSuffixToFileType(const QVector<CoreConfig::FileTypeSuffix> &p_fileTypeSuffixes);
|
||||||
|
|
||||||
signals:
|
signals:
|
||||||
void bufferRequested(Buffer *p_buffer, const QSharedPointer<FileOpenParameters> &p_paras);
|
void bufferRequested(Buffer *p_buffer, const QSharedPointer<FileOpenParameters> &p_paras);
|
||||||
|
|
||||||
@ -42,10 +46,19 @@ namespace vnotex
|
|||||||
|
|
||||||
void addBuffer(Buffer *p_buffer);
|
void addBuffer(Buffer *p_buffer);
|
||||||
|
|
||||||
|
bool openWithExternalProgram(const QString &p_filePath, const QString &p_name) const;
|
||||||
|
|
||||||
|
bool isSameTypeBuffer(const Buffer *p_buffer, const QString &p_typeName) const;
|
||||||
|
|
||||||
|
static QString findFileTypeByFile(const QString &p_filePath);
|
||||||
|
|
||||||
QSharedPointer<NameBasedServer<IBufferFactory>> m_bufferServer;
|
QSharedPointer<NameBasedServer<IBufferFactory>> m_bufferServer;
|
||||||
|
|
||||||
// Managed by QObject.
|
// Managed by QObject.
|
||||||
QVector<Buffer *> m_buffers;
|
QVector<Buffer *> m_buffers;
|
||||||
|
|
||||||
|
// Mapping from suffix to file type or external program name.
|
||||||
|
static QMap<QString, QString> s_suffixToFileType;
|
||||||
};
|
};
|
||||||
} // ns vnotex
|
} // ns vnotex
|
||||||
|
|
||||||
|
@ -3,6 +3,8 @@
|
|||||||
#include <QMetaEnum>
|
#include <QMetaEnum>
|
||||||
#include <QLocale>
|
#include <QLocale>
|
||||||
|
|
||||||
|
#include <utils/utils.h>
|
||||||
|
|
||||||
using namespace vnotex;
|
using namespace vnotex;
|
||||||
|
|
||||||
#define READSTR(key) readString(appObj, userObj, (key))
|
#define READSTR(key) readString(appObj, userObj, (key))
|
||||||
@ -10,6 +12,17 @@ using namespace vnotex;
|
|||||||
#define READBOOL(key) readBool(appObj, userObj, (key))
|
#define READBOOL(key) readBool(appObj, userObj, (key))
|
||||||
#define READSTRLIST(key) readStringList(appObj, userObj, (key))
|
#define READSTRLIST(key) readStringList(appObj, userObj, (key))
|
||||||
|
|
||||||
|
CoreConfig::FileTypeSuffix::FileTypeSuffix(const QString &p_name, const QStringList &p_suffixes)
|
||||||
|
: m_name(p_name),
|
||||||
|
m_suffixes(p_suffixes)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
bool CoreConfig::FileTypeSuffix::operator==(const FileTypeSuffix &p_other) const
|
||||||
|
{
|
||||||
|
return m_name == p_other.m_name && m_suffixes == p_other.m_suffixes;
|
||||||
|
}
|
||||||
|
|
||||||
QStringList CoreConfig::s_availableLocales;
|
QStringList CoreConfig::s_availableLocales;
|
||||||
|
|
||||||
CoreConfig::CoreConfig(ConfigMgr *p_mgr, IConfig *p_topConfig)
|
CoreConfig::CoreConfig(ConfigMgr *p_mgr, IConfig *p_topConfig)
|
||||||
@ -73,6 +86,8 @@ void CoreConfig::init(const QJsonObject &p_app,
|
|||||||
auto lineEnding = READSTR(QStringLiteral("line_ending"));
|
auto lineEnding = READSTR(QStringLiteral("line_ending"));
|
||||||
m_lineEnding = stringToLineEndingPolicy(lineEnding);
|
m_lineEnding = stringToLineEndingPolicy(lineEnding);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
loadFileTypeSuffixes(appObj, userObj);
|
||||||
}
|
}
|
||||||
|
|
||||||
QJsonObject CoreConfig::toJson() const
|
QJsonObject CoreConfig::toJson() const
|
||||||
@ -89,6 +104,7 @@ QJsonObject CoreConfig::toJson() const
|
|||||||
obj[QStringLiteral("history_max_count")] = m_historyMaxCount;
|
obj[QStringLiteral("history_max_count")] = m_historyMaxCount;
|
||||||
obj[QStringLiteral("per_notebook_history")] = m_perNotebookHistoryEnabled;
|
obj[QStringLiteral("per_notebook_history")] = m_perNotebookHistoryEnabled;
|
||||||
obj[QStringLiteral("line_ending")] = lineEndingPolicyToString(m_lineEnding);
|
obj[QStringLiteral("line_ending")] = lineEndingPolicyToString(m_lineEnding);
|
||||||
|
obj[QStringLiteral("file_type_suffixes")] = saveFileTypeSuffixes();
|
||||||
return obj;
|
return obj;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -241,3 +257,67 @@ void CoreConfig::setLineEndingPolicy(LineEndingPolicy p_ending)
|
|||||||
{
|
{
|
||||||
updateConfig(m_lineEnding, p_ending, this);
|
updateConfig(m_lineEnding, p_ending, this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void CoreConfig::loadFileTypeSuffixes(const QJsonObject &p_app, const QJsonObject &p_user)
|
||||||
|
{
|
||||||
|
m_fileTypeSuffixes.clear();
|
||||||
|
|
||||||
|
QJsonArray arr;
|
||||||
|
if (p_user.contains(QStringLiteral("file_type_suffixes"))) {
|
||||||
|
arr = p_user[QStringLiteral("file_type_suffixes")].toArray();
|
||||||
|
} else {
|
||||||
|
arr = p_app[QStringLiteral("file_type_suffixes")].toArray();
|
||||||
|
}
|
||||||
|
|
||||||
|
m_fileTypeSuffixes.reserve(arr.size());
|
||||||
|
|
||||||
|
for (int i = 0; i < arr.size(); ++i) {
|
||||||
|
const auto obj = arr[i].toObject();
|
||||||
|
const auto name = obj[QStringLiteral("name")].toString();
|
||||||
|
if (name.isEmpty()) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
const auto suffixes = readStringList(obj, QStringLiteral("suffixes"));
|
||||||
|
if (suffixes.isEmpty()) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
m_fileTypeSuffixes.push_back(FileTypeSuffix(name, Utils::toLower(suffixes)));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
QJsonArray CoreConfig::saveFileTypeSuffixes() const
|
||||||
|
{
|
||||||
|
QJsonArray arr;
|
||||||
|
for (const auto &fts : m_fileTypeSuffixes) {
|
||||||
|
QJsonObject obj;
|
||||||
|
obj[QStringLiteral("name")] = fts.m_name;
|
||||||
|
writeStringList(obj, QStringLiteral("suffixes"), fts.m_suffixes);
|
||||||
|
arr.push_back(obj);
|
||||||
|
}
|
||||||
|
return arr;
|
||||||
|
}
|
||||||
|
|
||||||
|
const QVector<CoreConfig::FileTypeSuffix> &CoreConfig::getFileTypeSuffixes() const
|
||||||
|
{
|
||||||
|
return m_fileTypeSuffixes;
|
||||||
|
}
|
||||||
|
|
||||||
|
void CoreConfig::setFileTypeSuffixes(const QVector<CoreConfig::FileTypeSuffix> &p_fileTypeSuffixes)
|
||||||
|
{
|
||||||
|
updateConfig(m_fileTypeSuffixes, p_fileTypeSuffixes, this);
|
||||||
|
}
|
||||||
|
|
||||||
|
const QStringList *CoreConfig::findFileTypeSuffix(const QString &p_name) const
|
||||||
|
{
|
||||||
|
if (p_name.isEmpty()) {
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (const auto &fts : m_fileTypeSuffixes) {
|
||||||
|
if (fts.m_name == p_name) {
|
||||||
|
return &fts.m_suffixes;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
@ -72,6 +72,19 @@ namespace vnotex
|
|||||||
};
|
};
|
||||||
Q_ENUM(Shortcut)
|
Q_ENUM(Shortcut)
|
||||||
|
|
||||||
|
struct FileTypeSuffix
|
||||||
|
{
|
||||||
|
FileTypeSuffix() = default;
|
||||||
|
|
||||||
|
FileTypeSuffix(const QString &p_name, const QStringList &p_suffixes);
|
||||||
|
|
||||||
|
bool operator==(const FileTypeSuffix &p_other) const;
|
||||||
|
|
||||||
|
QString m_name;
|
||||||
|
|
||||||
|
QStringList m_suffixes;
|
||||||
|
};
|
||||||
|
|
||||||
CoreConfig(ConfigMgr *p_mgr, IConfig *p_topConfig);
|
CoreConfig(ConfigMgr *p_mgr, IConfig *p_topConfig);
|
||||||
|
|
||||||
void init(const QJsonObject &p_app, const QJsonObject &p_user) Q_DECL_OVERRIDE;
|
void init(const QJsonObject &p_app, const QJsonObject &p_user) Q_DECL_OVERRIDE;
|
||||||
@ -115,6 +128,11 @@ namespace vnotex
|
|||||||
LineEndingPolicy getLineEndingPolicy() const;
|
LineEndingPolicy getLineEndingPolicy() const;
|
||||||
void setLineEndingPolicy(LineEndingPolicy p_ending);
|
void setLineEndingPolicy(LineEndingPolicy p_ending);
|
||||||
|
|
||||||
|
const QVector<FileTypeSuffix> &getFileTypeSuffixes() const;
|
||||||
|
void setFileTypeSuffixes(const QVector<FileTypeSuffix> &p_fileTypeSuffixes);
|
||||||
|
|
||||||
|
const QStringList *findFileTypeSuffix(const QString &p_name) const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
friend class MainConfig;
|
friend class MainConfig;
|
||||||
|
|
||||||
@ -124,6 +142,10 @@ namespace vnotex
|
|||||||
|
|
||||||
QJsonObject saveShortcuts() const;
|
QJsonObject saveShortcuts() const;
|
||||||
|
|
||||||
|
void loadFileTypeSuffixes(const QJsonObject &p_app, const QJsonObject &p_user);
|
||||||
|
|
||||||
|
QJsonArray saveFileTypeSuffixes() const;
|
||||||
|
|
||||||
// Theme name.
|
// Theme name.
|
||||||
QString m_theme;
|
QString m_theme;
|
||||||
|
|
||||||
@ -157,6 +179,8 @@ namespace vnotex
|
|||||||
|
|
||||||
LineEndingPolicy m_lineEnding = LineEndingPolicy::LF;
|
LineEndingPolicy m_lineEnding = LineEndingPolicy::LF;
|
||||||
|
|
||||||
|
QVector<FileTypeSuffix> m_fileTypeSuffixes;
|
||||||
|
|
||||||
static QStringList s_availableLocales;
|
static QStringList s_availableLocales;
|
||||||
};
|
};
|
||||||
} // ns vnotex
|
} // ns vnotex
|
||||||
|
@ -59,7 +59,6 @@ namespace vnotex
|
|||||||
|
|
||||||
const FileType &getContentType() const;
|
const FileType &getContentType() const;
|
||||||
|
|
||||||
protected:
|
|
||||||
void setContentType(int p_type);
|
void setContentType(int p_type);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
@ -50,6 +50,9 @@ namespace vnotex
|
|||||||
// Whether should save this file into session.
|
// Whether should save this file into session.
|
||||||
bool m_sessionEnabled = true;
|
bool m_sessionEnabled = true;
|
||||||
|
|
||||||
|
// Whether specify the built-in file type to open as or the external program to open with.
|
||||||
|
QString m_fileType;
|
||||||
|
|
||||||
std::function<void()> m_hooks[Hook::MaxHook];
|
std::function<void()> m_hooks[Hook::MaxHook];
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
@ -56,6 +56,13 @@ QJsonObject SessionConfig::ExternalProgram::toJson() const
|
|||||||
return jobj;
|
return jobj;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
QString SessionConfig::ExternalProgram::fetchCommand(const QString &p_file) const
|
||||||
|
{
|
||||||
|
auto command(m_command);
|
||||||
|
command.replace(QStringLiteral("%1"), QString("\"%1\"").arg(p_file));
|
||||||
|
return command;
|
||||||
|
}
|
||||||
|
|
||||||
SessionConfig::SessionConfig(ConfigMgr *p_mgr)
|
SessionConfig::SessionConfig(ConfigMgr *p_mgr)
|
||||||
: IConfig(p_mgr, nullptr)
|
: IConfig(p_mgr, nullptr)
|
||||||
{
|
{
|
||||||
@ -438,6 +445,16 @@ const QVector<SessionConfig::ExternalProgram> &SessionConfig::getExternalProgram
|
|||||||
return m_externalPrograms;
|
return m_externalPrograms;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const SessionConfig::ExternalProgram *SessionConfig::findExternalProgram(const QString &p_name) const
|
||||||
|
{
|
||||||
|
for (const auto &pro : m_externalPrograms) {
|
||||||
|
if (pro.m_name == p_name) {
|
||||||
|
return &pro;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
const QVector<HistoryItem> &SessionConfig::getHistory() const
|
const QVector<HistoryItem> &SessionConfig::getHistory() const
|
||||||
{
|
{
|
||||||
return m_history;
|
return m_history;
|
||||||
|
@ -66,6 +66,8 @@ namespace vnotex
|
|||||||
|
|
||||||
QJsonObject toJson() const;
|
QJsonObject toJson() const;
|
||||||
|
|
||||||
|
QString fetchCommand(const QString &p_file) const;
|
||||||
|
|
||||||
QString m_name;
|
QString m_name;
|
||||||
|
|
||||||
// %1: the file paths to open.
|
// %1: the file paths to open.
|
||||||
@ -134,6 +136,7 @@ namespace vnotex
|
|||||||
void removeQuickAccessFile(const QString &p_file);
|
void removeQuickAccessFile(const QString &p_file);
|
||||||
|
|
||||||
const QVector<ExternalProgram> &getExternalPrograms() const;
|
const QVector<ExternalProgram> &getExternalPrograms() const;
|
||||||
|
const ExternalProgram *findExternalProgram(const QString &p_name) const;
|
||||||
|
|
||||||
const QVector<HistoryItem> &getHistory() const;
|
const QVector<HistoryItem> &getHistory() const;
|
||||||
void addHistory(const HistoryItem &p_item);
|
void addHistory(const HistoryItem &p_item);
|
||||||
|
@ -99,6 +99,8 @@ void VNoteX::initNotebookMgr()
|
|||||||
|
|
||||||
void VNoteX::initBufferMgr()
|
void VNoteX::initBufferMgr()
|
||||||
{
|
{
|
||||||
|
BufferMgr::updateSuffixToFileType(ConfigMgr::getInst().getCoreConfig().getFileTypeSuffixes());
|
||||||
|
|
||||||
Q_ASSERT(!m_bufferMgr);
|
Q_ASSERT(!m_bufferMgr);
|
||||||
m_bufferMgr = new BufferMgr(this);
|
m_bufferMgr = new BufferMgr(this);
|
||||||
m_bufferMgr->init();
|
m_bufferMgr->init();
|
||||||
|
@ -6,7 +6,7 @@
|
|||||||
"version" : "3.12.0"
|
"version" : "3.12.0"
|
||||||
},
|
},
|
||||||
"core" : {
|
"core" : {
|
||||||
"theme" : "moonlight",
|
"theme" : "pure",
|
||||||
"locale" : "",
|
"locale" : "",
|
||||||
"shortcuts" : {
|
"shortcuts" : {
|
||||||
"FullScreen" : "F11",
|
"FullScreen" : "F11",
|
||||||
@ -61,6 +61,25 @@
|
|||||||
"MoveOneSplitRight" : "Ctrl+G, Shift+L",
|
"MoveOneSplitRight" : "Ctrl+G, Shift+L",
|
||||||
"OpenLastClosedFile" : "Ctrl+Shift+T"
|
"OpenLastClosedFile" : "Ctrl+Shift+T"
|
||||||
},
|
},
|
||||||
|
"file_type_suffixes" : [
|
||||||
|
{
|
||||||
|
"name" : "Markdown",
|
||||||
|
"suffixes" : [
|
||||||
|
"md",
|
||||||
|
"mkd",
|
||||||
|
"rmd",
|
||||||
|
"markdown"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name" : "Text",
|
||||||
|
"suffixes" : [
|
||||||
|
"txt",
|
||||||
|
"text",
|
||||||
|
"log"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
],
|
||||||
"shortcut_leader_key" : "Ctrl+G",
|
"shortcut_leader_key" : "Ctrl+G",
|
||||||
"toolbar_icon_size" : 18,
|
"toolbar_icon_size" : 18,
|
||||||
"docks_tabbar_icon_size" : 24,
|
"docks_tabbar_icon_size" : 24,
|
||||||
|
@ -204,3 +204,12 @@ QColor Utils::toColor(const QString &p_color)
|
|||||||
|
|
||||||
return QColor(p_color);
|
return QColor(p_color);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
QStringList Utils::toLower(const QStringList &p_list)
|
||||||
|
{
|
||||||
|
QStringList lowerList;
|
||||||
|
for (const auto &ele : p_list) {
|
||||||
|
lowerList << ele.toLower();
|
||||||
|
}
|
||||||
|
return lowerList;
|
||||||
|
}
|
||||||
|
@ -63,6 +63,8 @@ namespace vnotex
|
|||||||
static QJsonValue parseAndReadJson(const QJsonObject &p_obj, const QString &p_exp);
|
static QJsonValue parseAndReadJson(const QJsonObject &p_obj, const QString &p_exp);
|
||||||
|
|
||||||
static QColor toColor(const QString &p_color);
|
static QColor toColor(const QString &p_color);
|
||||||
|
|
||||||
|
static QStringList toLower(const QStringList &p_list);
|
||||||
};
|
};
|
||||||
} // ns vnotex
|
} // ns vnotex
|
||||||
|
|
||||||
|
@ -25,6 +25,7 @@
|
|||||||
#include <QLayout>
|
#include <QLayout>
|
||||||
#include <QPushButton>
|
#include <QPushButton>
|
||||||
#include <QSplitter>
|
#include <QSplitter>
|
||||||
|
#include <QFormLayout>
|
||||||
|
|
||||||
#include <core/global.h>
|
#include <core/global.h>
|
||||||
|
|
||||||
@ -460,3 +461,10 @@ bool WidgetUtils::distributeWidgetsOfSplitter(QSplitter *p_splitter)
|
|||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void WidgetUtils::clearLayout(QFormLayout *p_layout)
|
||||||
|
{
|
||||||
|
for (int i = p_layout->rowCount() - 1; i >= 0; --i) {
|
||||||
|
p_layout->removeRow(i);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -22,6 +22,7 @@ class QLayout;
|
|||||||
class QPushButton;
|
class QPushButton;
|
||||||
class QSplitter;
|
class QSplitter;
|
||||||
class QScreen;
|
class QScreen;
|
||||||
|
class QFormLayout;
|
||||||
|
|
||||||
namespace vnotex
|
namespace vnotex
|
||||||
{
|
{
|
||||||
@ -90,6 +91,8 @@ namespace vnotex
|
|||||||
|
|
||||||
static bool distributeWidgetsOfSplitter(QSplitter *p_splitter);
|
static bool distributeWidgetsOfSplitter(QSplitter *p_splitter);
|
||||||
|
|
||||||
|
static void clearLayout(QFormLayout *p_layout);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
static void resizeToHideScrollBar(QScrollArea *p_scroll, bool p_vertical, bool p_horizontal);
|
static void resizeToHideScrollBar(QScrollArea *p_scroll, bool p_vertical, bool p_horizontal);
|
||||||
};
|
};
|
||||||
|
132
src/widgets/dialogs/settings/fileassociationpage.cpp
Normal file
132
src/widgets/dialogs/settings/fileassociationpage.cpp
Normal file
@ -0,0 +1,132 @@
|
|||||||
|
#include "fileassociationpage.h"
|
||||||
|
|
||||||
|
#include <QFormLayout>
|
||||||
|
#include <QGroupBox>
|
||||||
|
#include <QVBoxLayout>
|
||||||
|
#include <QMap>
|
||||||
|
|
||||||
|
#include <widgets/widgetsfactory.h>
|
||||||
|
#include <widgets/lineedit.h>
|
||||||
|
#include <core/coreconfig.h>
|
||||||
|
#include <core/sessionconfig.h>
|
||||||
|
#include <core/configmgr.h>
|
||||||
|
#include <core/buffermgr.h>
|
||||||
|
#include <utils/widgetutils.h>
|
||||||
|
#include <utils/utils.h>
|
||||||
|
#include <core/vnotex.h>
|
||||||
|
#include <buffer/filetypehelper.h>
|
||||||
|
|
||||||
|
using namespace vnotex;
|
||||||
|
|
||||||
|
const char *FileAssociationPage::c_nameProperty = "name";
|
||||||
|
|
||||||
|
const QChar FileAssociationPage::c_suffixSeparator = QLatin1Char(';');
|
||||||
|
|
||||||
|
FileAssociationPage::FileAssociationPage(QWidget *p_parent)
|
||||||
|
: SettingsPage(p_parent)
|
||||||
|
{
|
||||||
|
setupUI();
|
||||||
|
}
|
||||||
|
|
||||||
|
void FileAssociationPage::setupUI()
|
||||||
|
{
|
||||||
|
auto mainLayout = new QVBoxLayout(this);
|
||||||
|
|
||||||
|
m_builtInFileTypesBox = new QGroupBox(tr("Built-In File Types"), this);
|
||||||
|
WidgetsFactory::createFormLayout(m_builtInFileTypesBox);
|
||||||
|
mainLayout->addWidget(m_builtInFileTypesBox);
|
||||||
|
|
||||||
|
m_externalProgramsBox = new QGroupBox(tr("External Programs"), this);
|
||||||
|
WidgetsFactory::createFormLayout(m_externalProgramsBox);
|
||||||
|
mainLayout->addWidget(m_externalProgramsBox);
|
||||||
|
}
|
||||||
|
|
||||||
|
void FileAssociationPage::loadInternal()
|
||||||
|
{
|
||||||
|
loadBuiltInTypesGroup(m_builtInFileTypesBox);
|
||||||
|
|
||||||
|
loadExternalProgramsGroup(m_externalProgramsBox);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool FileAssociationPage::saveInternal()
|
||||||
|
{
|
||||||
|
auto &coreConfig = ConfigMgr::getInst().getCoreConfig();
|
||||||
|
|
||||||
|
QVector<CoreConfig::FileTypeSuffix> fileTypeSuffixes;
|
||||||
|
|
||||||
|
auto lineEdits = m_builtInFileTypesBox->findChildren<QLineEdit *>(QString());
|
||||||
|
lineEdits << m_externalProgramsBox->findChildren<QLineEdit *>(QString());
|
||||||
|
fileTypeSuffixes.reserve(lineEdits.size());
|
||||||
|
for (const auto lineEdit : lineEdits) {
|
||||||
|
auto name = lineEdit->property(c_nameProperty).toString();
|
||||||
|
if (name.isEmpty()) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
auto suffixes = lineEdit->text().split(c_suffixSeparator, Qt::SkipEmptyParts);
|
||||||
|
if (suffixes.isEmpty()) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
fileTypeSuffixes.push_back(CoreConfig::FileTypeSuffix(name, Utils::toLower(suffixes)));
|
||||||
|
}
|
||||||
|
|
||||||
|
coreConfig.setFileTypeSuffixes(fileTypeSuffixes);
|
||||||
|
|
||||||
|
FileTypeHelper::getInst().reload();
|
||||||
|
|
||||||
|
BufferMgr::updateSuffixToFileType(coreConfig.getFileTypeSuffixes());
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
QString FileAssociationPage::title() const
|
||||||
|
{
|
||||||
|
return tr("File Associations");
|
||||||
|
}
|
||||||
|
|
||||||
|
void FileAssociationPage::loadBuiltInTypesGroup(QGroupBox *p_box)
|
||||||
|
{
|
||||||
|
auto layout = static_cast<QFormLayout *>(p_box->layout());
|
||||||
|
WidgetUtils::clearLayout(layout);
|
||||||
|
|
||||||
|
const auto &types = FileTypeHelper::getInst().getAllFileTypes();
|
||||||
|
|
||||||
|
for (const auto &ft : types) {
|
||||||
|
if (ft.m_type == FileType::Others) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto lineEdit = WidgetsFactory::createLineEdit(p_box);
|
||||||
|
layout->addRow(ft.m_displayName, lineEdit);
|
||||||
|
connect(lineEdit, &QLineEdit::textChanged,
|
||||||
|
this, &FileAssociationPage::pageIsChanged);
|
||||||
|
|
||||||
|
lineEdit->setPlaceholderText(tr("Suffixes separated by ;"));
|
||||||
|
lineEdit->setToolTip(tr("List of suffixes for this file type"));
|
||||||
|
lineEdit->setProperty(c_nameProperty, ft.m_typeName);
|
||||||
|
lineEdit->setText(ft.m_suffixes.join(c_suffixSeparator));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void FileAssociationPage::loadExternalProgramsGroup(QGroupBox *p_box)
|
||||||
|
{
|
||||||
|
auto layout = static_cast<QFormLayout *>(p_box->layout());
|
||||||
|
WidgetUtils::clearLayout(layout);
|
||||||
|
|
||||||
|
const auto &coreConfig = ConfigMgr::getInst().getCoreConfig();
|
||||||
|
const auto &sessionConfig = ConfigMgr::getInst().getSessionConfig();
|
||||||
|
for (const auto &pro : sessionConfig.getExternalPrograms()) {
|
||||||
|
auto lineEdit = WidgetsFactory::createLineEdit(p_box);
|
||||||
|
layout->addRow(pro.m_name, lineEdit);
|
||||||
|
connect(lineEdit, &QLineEdit::textChanged,
|
||||||
|
this, &FileAssociationPage::pageIsChanged);
|
||||||
|
|
||||||
|
lineEdit->setPlaceholderText(tr("Suffixes separated by ;"));
|
||||||
|
lineEdit->setToolTip(tr("List of suffixes to open with external program"));
|
||||||
|
lineEdit->setProperty(c_nameProperty, pro.m_name);
|
||||||
|
|
||||||
|
auto suffixes = coreConfig.findFileTypeSuffix(pro.m_name);
|
||||||
|
if (suffixes) {
|
||||||
|
lineEdit->setText(suffixes->join(c_suffixSeparator));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
40
src/widgets/dialogs/settings/fileassociationpage.h
Normal file
40
src/widgets/dialogs/settings/fileassociationpage.h
Normal file
@ -0,0 +1,40 @@
|
|||||||
|
#ifndef FILEASSOCIATIONPAGE_H
|
||||||
|
#define FILEASSOCIATIONPAGE_H
|
||||||
|
|
||||||
|
#include "settingspage.h"
|
||||||
|
|
||||||
|
class QGroupBox;
|
||||||
|
|
||||||
|
namespace vnotex
|
||||||
|
{
|
||||||
|
class FileAssociationPage : public SettingsPage
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
public:
|
||||||
|
explicit FileAssociationPage(QWidget *p_parent = nullptr);
|
||||||
|
|
||||||
|
QString title() const Q_DECL_OVERRIDE;
|
||||||
|
|
||||||
|
protected:
|
||||||
|
void loadInternal() Q_DECL_OVERRIDE;
|
||||||
|
|
||||||
|
bool saveInternal() Q_DECL_OVERRIDE;
|
||||||
|
|
||||||
|
private:
|
||||||
|
void setupUI();
|
||||||
|
|
||||||
|
void loadBuiltInTypesGroup(QGroupBox *p_box);
|
||||||
|
|
||||||
|
void loadExternalProgramsGroup(QGroupBox *p_box);
|
||||||
|
|
||||||
|
QGroupBox *m_builtInFileTypesBox = nullptr;
|
||||||
|
|
||||||
|
QGroupBox *m_externalProgramsBox = nullptr;
|
||||||
|
|
||||||
|
static const char *c_nameProperty;
|
||||||
|
|
||||||
|
static const QChar c_suffixSeparator;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif // FILEASSOCIATIONPAGE_H
|
@ -27,6 +27,7 @@
|
|||||||
#include "imagehostpage.h"
|
#include "imagehostpage.h"
|
||||||
#include "vipage.h"
|
#include "vipage.h"
|
||||||
#include "notemanagementpage.h"
|
#include "notemanagementpage.h"
|
||||||
|
#include "fileassociationpage.h"
|
||||||
|
|
||||||
using namespace vnotex;
|
using namespace vnotex;
|
||||||
|
|
||||||
@ -173,6 +174,12 @@ void SettingsDialog::setupPages()
|
|||||||
*/
|
*/
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// File Association.
|
||||||
|
{
|
||||||
|
auto page = new FileAssociationPage(this);
|
||||||
|
addPage(page);
|
||||||
|
}
|
||||||
|
|
||||||
setChangesUnsaved(false);
|
setChangesUnsaved(false);
|
||||||
m_pageExplorer->setCurrentItem(m_pageExplorer->topLevelItem(0), 0, QItemSelectionModel::ClearAndSelect);
|
m_pageExplorer->setCurrentItem(m_pageExplorer->topLevelItem(0), 0, QItemSelectionModel::ClearAndSelect);
|
||||||
m_pageExplorer->expandAll();
|
m_pageExplorer->expandAll();
|
||||||
|
@ -17,7 +17,6 @@
|
|||||||
#include "mainwindow.h"
|
#include "mainwindow.h"
|
||||||
#include <utils/iconutils.h>
|
#include <utils/iconutils.h>
|
||||||
#include <utils/docsutils.h>
|
#include <utils/docsutils.h>
|
||||||
#include <utils/processutils.h>
|
|
||||||
#include "treewidget.h"
|
#include "treewidget.h"
|
||||||
#include "listwidget.h"
|
#include "listwidget.h"
|
||||||
#include "dialogs/notepropertiesdialog.h"
|
#include "dialogs/notepropertiesdialog.h"
|
||||||
@ -38,6 +37,7 @@
|
|||||||
#include <core/coreconfig.h>
|
#include <core/coreconfig.h>
|
||||||
#include <core/sessionconfig.h>
|
#include <core/sessionconfig.h>
|
||||||
#include <core/widgetconfig.h>
|
#include <core/widgetconfig.h>
|
||||||
|
#include <buffer/filetypehelper.h>
|
||||||
|
|
||||||
using namespace vnotex;
|
using namespace vnotex;
|
||||||
|
|
||||||
@ -2106,15 +2106,32 @@ void NotebookNodeExplorer::addOpenWithMenu(QMenu *p_menu, bool p_master)
|
|||||||
{
|
{
|
||||||
auto subMenu = p_menu->addMenu(tr("Open &With"));
|
auto subMenu = p_menu->addMenu(tr("Open &With"));
|
||||||
|
|
||||||
|
const auto &types = FileTypeHelper::getInst().getAllFileTypes();
|
||||||
|
|
||||||
|
for (const auto &ft : types) {
|
||||||
|
if (ft.m_type == FileType::Others) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
QAction *act = subMenu->addAction(ft.m_displayName);
|
||||||
|
connect(act, &QAction::triggered,
|
||||||
|
this, [this, act, p_master]() {
|
||||||
|
openSelectedNodesWithProgram(act->data().toString(), p_master);
|
||||||
|
});
|
||||||
|
act->setData(ft.m_typeName);
|
||||||
|
}
|
||||||
|
|
||||||
|
subMenu->addSeparator();
|
||||||
|
|
||||||
{
|
{
|
||||||
const auto &sessionConfig = ConfigMgr::getInst().getSessionConfig();
|
const auto &sessionConfig = ConfigMgr::getInst().getSessionConfig();
|
||||||
for (const auto &pro : sessionConfig.getExternalPrograms()) {
|
for (const auto &pro : sessionConfig.getExternalPrograms()) {
|
||||||
QAction *act = subMenu->addAction(pro.m_name);
|
QAction *act = subMenu->addAction(pro.m_name);
|
||||||
connect(act, &QAction::triggered,
|
connect(act, &QAction::triggered,
|
||||||
this, [this, act, p_master]() {
|
this, [this, act, p_master]() {
|
||||||
openSelectedNodesWithCommand(act->data().toString(), p_master);
|
openSelectedNodesWithProgram(act->data().toString(), p_master);
|
||||||
});
|
});
|
||||||
act->setData(pro.m_command);
|
act->setData(pro.m_name);
|
||||||
WidgetUtils::addActionShortcutText(act, pro.m_shortcut);
|
WidgetUtils::addActionShortcutText(act, pro.m_shortcut);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -2125,7 +2142,7 @@ void NotebookNodeExplorer::addOpenWithMenu(QMenu *p_menu, bool p_master)
|
|||||||
auto defaultAct = subMenu->addAction(tr("System Default Program"));
|
auto defaultAct = subMenu->addAction(tr("System Default Program"));
|
||||||
connect(defaultAct, &QAction::triggered,
|
connect(defaultAct, &QAction::triggered,
|
||||||
this, [this, defaultAct, p_master]() {
|
this, [this, defaultAct, p_master]() {
|
||||||
openSelectedNodesWithCommand(QString(), p_master);
|
openSelectedNodesWithProgram(QString(), p_master);
|
||||||
});
|
});
|
||||||
const auto &coreConfig = ConfigMgr::getInst().getCoreConfig();
|
const auto &coreConfig = ConfigMgr::getInst().getCoreConfig();
|
||||||
WidgetUtils::addActionShortcutText(defaultAct, coreConfig.getShortcut(CoreConfig::OpenWithDefaultProgram));
|
WidgetUtils::addActionShortcutText(defaultAct, coreConfig.getShortcut(CoreConfig::OpenWithDefaultProgram));
|
||||||
@ -2157,7 +2174,7 @@ void NotebookNodeExplorer::setupShortcuts()
|
|||||||
if (!isCombinedExploreMode()) {
|
if (!isCombinedExploreMode()) {
|
||||||
isMaster = m_masterExplorer->hasFocus();
|
isMaster = m_masterExplorer->hasFocus();
|
||||||
}
|
}
|
||||||
openSelectedNodesWithCommand(QString(), isMaster);
|
openSelectedNodesWithProgram(QString(), isMaster);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -2165,21 +2182,21 @@ void NotebookNodeExplorer::setupShortcuts()
|
|||||||
const auto &sessionConfig = ConfigMgr::getInst().getSessionConfig();
|
const auto &sessionConfig = ConfigMgr::getInst().getSessionConfig();
|
||||||
for (const auto &pro : sessionConfig.getExternalPrograms()) {
|
for (const auto &pro : sessionConfig.getExternalPrograms()) {
|
||||||
auto shortcut = WidgetUtils::createShortcut(pro.m_shortcut, this);
|
auto shortcut = WidgetUtils::createShortcut(pro.m_shortcut, this);
|
||||||
const auto &command = pro.m_command;
|
const auto &name = pro.m_name;
|
||||||
if (shortcut) {
|
if (shortcut) {
|
||||||
connect(shortcut, &QShortcut::activated,
|
connect(shortcut, &QShortcut::activated,
|
||||||
this, [this, command]() {
|
this, [this, name]() {
|
||||||
bool isMaster = true;
|
bool isMaster = true;
|
||||||
if (!isCombinedExploreMode()) {
|
if (!isCombinedExploreMode()) {
|
||||||
isMaster = m_masterExplorer->hasFocus();
|
isMaster = m_masterExplorer->hasFocus();
|
||||||
}
|
}
|
||||||
openSelectedNodesWithCommand(command, isMaster);
|
openSelectedNodesWithProgram(name, isMaster);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void NotebookNodeExplorer::openSelectedNodesWithCommand(const QString &p_command, bool p_master)
|
void NotebookNodeExplorer::openSelectedNodesWithProgram(const QString &p_name, bool p_master)
|
||||||
{
|
{
|
||||||
const bool closeBefore = ConfigMgr::getInst().getWidgetConfig().getNodeExplorerCloseBeforeOpenWithEnabled();
|
const bool closeBefore = ConfigMgr::getInst().getWidgetConfig().getNodeExplorerCloseBeforeOpenWithEnabled();
|
||||||
const auto files = getSelectedNodesPath(p_master);
|
const auto files = getSelectedNodesPath(p_master);
|
||||||
@ -2196,12 +2213,12 @@ void NotebookNodeExplorer::openSelectedNodesWithCommand(const QString &p_command
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (p_command.isEmpty()) {
|
if (p_name.isEmpty()) {
|
||||||
WidgetUtils::openUrlByDesktop(QUrl::fromLocalFile(file));
|
WidgetUtils::openUrlByDesktop(QUrl::fromLocalFile(file));
|
||||||
} else {
|
} else {
|
||||||
auto command = p_command;
|
auto paras = QSharedPointer<FileOpenParameters>::create();
|
||||||
command.replace(QStringLiteral("%1"), QString("\"%1\"").arg(file));
|
paras->m_fileType = p_name;
|
||||||
ProcessUtils::startDetached(command);
|
emit VNoteX::getInst().openFileRequested(file, paras);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -297,7 +297,7 @@ namespace vnotex
|
|||||||
|
|
||||||
QStringList getSelectedNodesPath(bool p_master) const;
|
QStringList getSelectedNodesPath(bool p_master) const;
|
||||||
|
|
||||||
void openSelectedNodesWithCommand(const QString &p_command, bool p_master);
|
void openSelectedNodesWithProgram(const QString &p_name, bool p_master);
|
||||||
|
|
||||||
bool belongsToMasterExplorer(const Node *p_node) const;
|
bool belongsToMasterExplorer(const Node *p_node) const;
|
||||||
|
|
||||||
|
@ -9,7 +9,6 @@ using namespace vnotex;
|
|||||||
WebPage::WebPage(QWidget *p_parent)
|
WebPage::WebPage(QWidget *p_parent)
|
||||||
: QWebEnginePage(p_parent)
|
: QWebEnginePage(p_parent)
|
||||||
{
|
{
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool WebPage::acceptNavigationRequest(const QUrl &p_url,
|
bool WebPage::acceptNavigationRequest(const QUrl &p_url,
|
||||||
@ -29,7 +28,7 @@ bool WebPage::acceptNavigationRequest(const QUrl &p_url,
|
|||||||
if (scheme == QStringLiteral("data")) {
|
if (scheme == QStringLiteral("data")) {
|
||||||
// Qt 5.12 and above will trigger this when calling QWebEngineView::setHtml().
|
// Qt 5.12 and above will trigger this when calling QWebEngineView::setHtml().
|
||||||
return true;
|
return true;
|
||||||
} else if (scheme == QStringLiteral("chrome-devtools")) {
|
} else if (scheme == QStringLiteral("chrome-devtools") || scheme == QStringLiteral("devtools")) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -22,6 +22,7 @@ SOURCES += \
|
|||||||
$$PWD/dialogs/selectionitemwidget.cpp \
|
$$PWD/dialogs/selectionitemwidget.cpp \
|
||||||
$$PWD/dialogs/settings/appearancepage.cpp \
|
$$PWD/dialogs/settings/appearancepage.cpp \
|
||||||
$$PWD/dialogs/settings/editorpage.cpp \
|
$$PWD/dialogs/settings/editorpage.cpp \
|
||||||
|
$$PWD/dialogs/settings/fileassociationpage.cpp \
|
||||||
$$PWD/dialogs/settings/generalpage.cpp \
|
$$PWD/dialogs/settings/generalpage.cpp \
|
||||||
$$PWD/dialogs/settings/imagehostpage.cpp \
|
$$PWD/dialogs/settings/imagehostpage.cpp \
|
||||||
$$PWD/dialogs/settings/markdowneditorpage.cpp \
|
$$PWD/dialogs/settings/markdowneditorpage.cpp \
|
||||||
@ -150,6 +151,7 @@ HEADERS += \
|
|||||||
$$PWD/dialogs/selectionitemwidget.h \
|
$$PWD/dialogs/selectionitemwidget.h \
|
||||||
$$PWD/dialogs/settings/appearancepage.h \
|
$$PWD/dialogs/settings/appearancepage.h \
|
||||||
$$PWD/dialogs/settings/editorpage.h \
|
$$PWD/dialogs/settings/editorpage.h \
|
||||||
|
$$PWD/dialogs/settings/fileassociationpage.h \
|
||||||
$$PWD/dialogs/settings/generalpage.h \
|
$$PWD/dialogs/settings/generalpage.h \
|
||||||
$$PWD/dialogs/settings/imagehostpage.h \
|
$$PWD/dialogs/settings/imagehostpage.h \
|
||||||
$$PWD/dialogs/settings/markdowneditorpage.h \
|
$$PWD/dialogs/settings/markdowneditorpage.h \
|
||||||
|
Loading…
x
Reference in New Issue
Block a user