mirror of
https://github.com/x-tools-author/x-tools.git
synced 2025-09-15 15:28:40 +08:00
chore: add module to project
This commit is contained in:
parent
4f129825f5
commit
6bfb2e3605
BIN
xapps/xsvg/300x300.png
Normal file
BIN
xapps/xsvg/300x300.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 13 KiB |
BIN
xapps/xsvg/res/translations/xSvg_en.qm
Normal file
BIN
xapps/xsvg/res/translations/xSvg_en.qm
Normal file
Binary file not shown.
122
xapps/xsvg/res/translations/xSvg_en.ts
Normal file
122
xapps/xsvg/res/translations/xSvg_en.ts
Normal file
@ -0,0 +1,122 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!DOCTYPE TS>
|
||||
<TS version="2.1" language="en_US">
|
||||
<context>
|
||||
<name>MainWindow</name>
|
||||
<message>
|
||||
<location filename="../../Source/MainWindow.ui" line="14"/>
|
||||
<source>Form</source>
|
||||
<translation></translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
<name>SettingsMenu</name>
|
||||
<message>
|
||||
<location filename="../../Source/SettingsMenu.ui" line="26"/>
|
||||
<source>Padding</source>
|
||||
<translation></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../../Source/SettingsMenu.ui" line="40"/>
|
||||
<source>Enable export parameters</source>
|
||||
<translation></translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
<name>xSvg::MainWindow</name>
|
||||
<message>
|
||||
<location filename="../../Source/MainWindow.cpp" line="76"/>
|
||||
<source>Import SVG Files</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../../Source/MainWindow.cpp" line="77"/>
|
||||
<source>Select a folder to import SVG files now ?</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../../Source/MainWindow.cpp" line="132"/>
|
||||
<source>Open Path</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../../Source/MainWindow.cpp" line="137"/>
|
||||
<source>Open File Location</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../../Source/MainWindow.cpp" line="142"/>
|
||||
<source>Save As...</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../../Source/MainWindow.cpp" line="146"/>
|
||||
<source>Copy Full Path</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../../Source/MainWindow.cpp" line="150"/>
|
||||
<source>Copy File Name</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../../Source/MainWindow.cpp" line="157"/>
|
||||
<source>Filter
|
||||
Text</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../../Source/MainWindow.cpp" line="178"/>
|
||||
<source>Export
|
||||
Format</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../../Source/MainWindow.cpp" line="203"/>
|
||||
<source>Icon
|
||||
Size</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../../Source/MainWindow.cpp" line="230"/>
|
||||
<source>Fill
|
||||
Color</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../../Source/MainWindow.cpp" line="246"/>
|
||||
<source>Select Color</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../../Source/MainWindow.cpp" line="276"/>
|
||||
<source>Open SVG Path</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../../Source/MainWindow.cpp" line="368"/>
|
||||
<source>Trial Limit</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../../Source/MainWindow.cpp" line="369"/>
|
||||
<source>The operation is not supported by trial edition, please purchase full license.</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../../Source/MainWindow.cpp" line="382"/>
|
||||
<source>Copy to...</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../../Source/MainWindow.cpp" line="457"/>
|
||||
<source>NO SVG FOUND</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../../Source/MainWindow.cpp" line="458"/>
|
||||
<source>The path you selected has no svg file(s), please selected one has svg file(s) then try again</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
</context>
|
||||
</TS>
|
||||
BIN
xapps/xsvg/res/translations/xSvg_zh_CN.qm
Normal file
BIN
xapps/xsvg/res/translations/xSvg_zh_CN.qm
Normal file
Binary file not shown.
206
xapps/xsvg/res/translations/xSvg_zh_CN.ts
Normal file
206
xapps/xsvg/res/translations/xSvg_zh_CN.ts
Normal file
@ -0,0 +1,206 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!DOCTYPE TS>
|
||||
<TS version="2.1" language="zh_CN">
|
||||
<context>
|
||||
<name>MainWindow</name>
|
||||
<message>
|
||||
<location filename="../../Source/MainWindow.ui" line="14"/>
|
||||
<source>Form</source>
|
||||
<translation></translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Import SVG Files</source>
|
||||
<translation type="vanished">导入SVG文件</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Select a folder to import SVG files now ?</source>
|
||||
<translation type="vanished">现在选择一个文件夹以导入SVG文件来预览?</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Open Path</source>
|
||||
<translation type="vanished">打开文件夹</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Open File Location</source>
|
||||
<translation type="vanished">打开文件路径</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Save As...</source>
|
||||
<translation type="vanished">另存为...</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Copy Full Path</source>
|
||||
<translation type="vanished">复制全路径</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Copy File Name</source>
|
||||
<translation type="vanished">复制文件夹</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Filter
|
||||
Text</source>
|
||||
<translation type="vanished">过滤
|
||||
文本</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Export
|
||||
Format</source>
|
||||
<translation type="vanished">导出
|
||||
格式</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Icon
|
||||
Size</source>
|
||||
<translation type="vanished">图标
|
||||
大小</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Fill
|
||||
Color</source>
|
||||
<translation type="vanished">填充
|
||||
颜色</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Select Color</source>
|
||||
<translation type="vanished">选择颜色</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Open SVG Path</source>
|
||||
<translation type="vanished">打开文件路径</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Trial Limit</source>
|
||||
<translation type="vanished">试用限制</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>The operation is not supported by trial edition, please purchase full license.</source>
|
||||
<translation type="vanished">试用版不支持此项操作,请购买完整许可后重试。</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Copy to...</source>
|
||||
<translation type="vanished">复制至...</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>NO SVG FOUND</source>
|
||||
<translation type="vanished">未找到任何SVG文件</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>The path you selected has no svg file(s), please selected one has svg file(s) then try again</source>
|
||||
<translation type="vanished">你选择的文件夹未包含任何SVG文件,请选择一个包含SVG文件的文件夹后重试</translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
<name>SettingsMenu</name>
|
||||
<message>
|
||||
<location filename="../../Source/SettingsMenu.ui" line="26"/>
|
||||
<source>Padding</source>
|
||||
<translation>内容边框</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../../Source/SettingsMenu.ui" line="40"/>
|
||||
<source>Enable export parameters</source>
|
||||
<translation>使能导出参数</translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
<name>xSvg::MainWindow</name>
|
||||
<message>
|
||||
<location filename="../../Source/MainWindow.cpp" line="76"/>
|
||||
<source>Import SVG Files</source>
|
||||
<translation type="unfinished">导入SVG文件</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../../Source/MainWindow.cpp" line="77"/>
|
||||
<source>Select a folder to import SVG files now ?</source>
|
||||
<translation type="unfinished">现在选择一个文件夹以导入SVG文件来预览?</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../../Source/MainWindow.cpp" line="132"/>
|
||||
<source>Open Path</source>
|
||||
<translation type="unfinished">打开文件夹</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../../Source/MainWindow.cpp" line="137"/>
|
||||
<source>Open File Location</source>
|
||||
<translation type="unfinished">打开文件路径</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../../Source/MainWindow.cpp" line="142"/>
|
||||
<source>Save As...</source>
|
||||
<translation type="unfinished">另存为...</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../../Source/MainWindow.cpp" line="146"/>
|
||||
<source>Copy Full Path</source>
|
||||
<translation type="unfinished">复制全路径</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../../Source/MainWindow.cpp" line="150"/>
|
||||
<source>Copy File Name</source>
|
||||
<translation type="unfinished">复制文件夹</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../../Source/MainWindow.cpp" line="157"/>
|
||||
<source>Filter
|
||||
Text</source>
|
||||
<translation type="unfinished">过滤
|
||||
文本</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../../Source/MainWindow.cpp" line="178"/>
|
||||
<source>Export
|
||||
Format</source>
|
||||
<translation type="unfinished">导出
|
||||
格式</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../../Source/MainWindow.cpp" line="203"/>
|
||||
<source>Icon
|
||||
Size</source>
|
||||
<translation type="unfinished">图标
|
||||
大小</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../../Source/MainWindow.cpp" line="230"/>
|
||||
<source>Fill
|
||||
Color</source>
|
||||
<translation type="unfinished">填充
|
||||
颜色</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../../Source/MainWindow.cpp" line="246"/>
|
||||
<source>Select Color</source>
|
||||
<translation type="unfinished">选择颜色</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../../Source/MainWindow.cpp" line="276"/>
|
||||
<source>Open SVG Path</source>
|
||||
<translation type="unfinished">打开文件路径</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../../Source/MainWindow.cpp" line="368"/>
|
||||
<source>Trial Limit</source>
|
||||
<translation type="unfinished">试用限制</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../../Source/MainWindow.cpp" line="369"/>
|
||||
<source>The operation is not supported by trial edition, please purchase full license.</source>
|
||||
<translation type="unfinished">试用版不支持此项操作,请购买完整许可后重试。</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../../Source/MainWindow.cpp" line="382"/>
|
||||
<source>Copy to...</source>
|
||||
<translation type="unfinished">复制至...</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../../Source/MainWindow.cpp" line="457"/>
|
||||
<source>NO SVG FOUND</source>
|
||||
<translation type="unfinished">未找到任何SVG文件</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../../Source/MainWindow.cpp" line="458"/>
|
||||
<source>The path you selected has no svg file(s), please selected one has svg file(s) then try again</source>
|
||||
<translation type="unfinished">你选择的文件夹未包含任何SVG文件,请选择一个包含SVG文件的文件夹后重试</translation>
|
||||
</message>
|
||||
</context>
|
||||
</TS>
|
||||
24
xapps/xsvg/src/main.cpp
Normal file
24
xapps/xsvg/src/main.cpp
Normal file
@ -0,0 +1,24 @@
|
||||
/***************************************************************************************************
|
||||
* Copyright 2024 x-tools-author(x-tools@outlook.com). All rights reserved.
|
||||
*
|
||||
* The file is encoded using "utf8 with bom", it is a part of xTools project.
|
||||
*
|
||||
* xTools is licensed according to the terms in the file LICENCE(GPL V3) in the root of the source
|
||||
* code directory.
|
||||
**************************************************************************************************/
|
||||
#include "MainWindow.h"
|
||||
#include "xApp/Source/xApp.h"
|
||||
#include "xLicense/Source/PayJsApi.h"
|
||||
|
||||
int main(const int argc, char *argv[])
|
||||
{
|
||||
Q_INIT_RESOURCE(xTools);
|
||||
Q_INIT_RESOURCE(xApp);
|
||||
|
||||
xApp::PayJsApi::singleton().setPrice(10 * 10 * 10);
|
||||
return xApp::exec<xSvg::MainWindow>(argc,
|
||||
argv,
|
||||
QString("xSvg"),
|
||||
QString(X_SVG_VERSION),
|
||||
QString("50263Qsaker2018.xSvg"));
|
||||
}
|
||||
473
xapps/xsvg/src/mainwindow.cpp
Normal file
473
xapps/xsvg/src/mainwindow.cpp
Normal file
@ -0,0 +1,473 @@
|
||||
/***************************************************************************************************
|
||||
* Copyright 2024 x-tools-author(x-tools@outlook.com). All rights reserved.
|
||||
*
|
||||
* The file is encoded using "utf8 with bom", it is a part of xTools project.
|
||||
*
|
||||
* xTools is licensed according to the terms in the file LICENCE(GPL V3) in the root of the source
|
||||
* code directory.
|
||||
**************************************************************************************************/
|
||||
#include "MainWindow.h"
|
||||
#include "ui_MainWindow.h"
|
||||
|
||||
#include <QClipboard>
|
||||
#include <QColorDialog>
|
||||
#include <QComboBox>
|
||||
#include <QDesktopServices>
|
||||
#include <QFileDialog>
|
||||
#include <QLabel>
|
||||
#include <QLineEdit>
|
||||
#include <QMessageBox>
|
||||
#include <QPainter>
|
||||
#include <QPushButton>
|
||||
#include <QString>
|
||||
#include <QTimer>
|
||||
#include <QToolBar>
|
||||
#include <QVBoxLayout>
|
||||
#include <QWidgetAction>
|
||||
|
||||
#include "Common/xTools.h"
|
||||
#include "SettingsMenu.h"
|
||||
#include "SvgFileDataModel.h"
|
||||
#include "SvgItemDelegate.h"
|
||||
#include "xLicense/Source/LicenseManager.h"
|
||||
|
||||
namespace xSvg {
|
||||
|
||||
MainWindow::MainWindow(QWidget *parent)
|
||||
: xApp::MainWindow(parent)
|
||||
, ui(new Ui::MainWindow)
|
||||
, m_model{nullptr}
|
||||
{
|
||||
initToolBar();
|
||||
initMenuBar();
|
||||
|
||||
m_centralWidget = new QWidget(this);
|
||||
ui->setupUi(m_centralWidget);
|
||||
ui->tableView->installEventFilter(this);
|
||||
ui->tableView->horizontalHeader()->setSectionResizeMode(QHeaderView::ResizeMode::Fixed);
|
||||
ui->tableView->horizontalHeader()->hide();
|
||||
ui->tableView->verticalHeader()->hide();
|
||||
ui->tableView->setItemDelegate(new SvgItemDelegate(this));
|
||||
|
||||
ui->tableView->setContextMenuPolicy(Qt::CustomContextMenu);
|
||||
QMenu *menu = new QMenu(ui->tableView);
|
||||
menu->addAction(m_actions.openPath);
|
||||
menu->addAction(m_actions.openFileLocation);
|
||||
menu->addAction(m_actions.saveAs);
|
||||
menu->addAction(m_actions.copyFullPath);
|
||||
menu->addAction(m_actions.copyFileName);
|
||||
connect(ui->tableView, &QWidget::customContextMenuRequested, this, [=](const QPoint &pos) {
|
||||
menu->exec(ui->tableView->mapToGlobal(pos));
|
||||
});
|
||||
|
||||
setMinimumSize(1280, 680);
|
||||
setCentralWidget(m_centralWidget);
|
||||
}
|
||||
|
||||
MainWindow::~MainWindow()
|
||||
{
|
||||
delete ui;
|
||||
}
|
||||
|
||||
void MainWindow::showTips()
|
||||
{
|
||||
QTimer::singleShot(500, this, [=]() {
|
||||
int ret = QMessageBox::information(this,
|
||||
tr("Import SVG Files"),
|
||||
tr("Select a folder to import SVG files now ?"),
|
||||
QMessageBox::Yes | QMessageBox::No);
|
||||
if (ret == QMessageBox::Yes) {
|
||||
openPath();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
bool MainWindow::eventFilter(QObject *obj, QEvent *event)
|
||||
{
|
||||
if (obj == ui->tableView && event->type() == QEvent::Resize) {
|
||||
updateView();
|
||||
}
|
||||
return xApp::MainWindow::eventFilter(obj, event);
|
||||
}
|
||||
|
||||
void MainWindow::initMenuBar()
|
||||
{
|
||||
m_exitAction->setIcon(materialIcon(QString("close.svg")));
|
||||
m_fileMenu->insertAction(m_exitAction, m_actions.openPath);
|
||||
m_fileMenu->insertAction(m_exitAction, m_actions.openFileLocation);
|
||||
//m_fileMenu->insertSeparator(m_exitAction);
|
||||
m_fileMenu->insertAction(m_exitAction, m_actions.saveAs);
|
||||
//m_fileMenu->insertSeparator(m_exitAction);
|
||||
m_fileMenu->insertAction(m_exitAction, m_actions.copyFullPath);
|
||||
m_fileMenu->insertAction(m_exitAction, m_actions.copyFileName);
|
||||
}
|
||||
|
||||
void MainWindow::initToolBar()
|
||||
{
|
||||
QToolBar *toolBar = new QToolBar(this);
|
||||
addToolBar(Qt::TopToolBarArea, toolBar);
|
||||
toolBar->setToolButtonStyle(Qt::ToolButtonStyle::ToolButtonIconOnly);
|
||||
toolBar->setMovable(false);
|
||||
toolBar->setFloatable(false);
|
||||
toolBar->setOrientation(Qt::Orientation::Horizontal);
|
||||
|
||||
initToolBarActions(toolBar);
|
||||
toolBar->addSeparator();
|
||||
addSpacer(toolBar, 4);
|
||||
initToolBarFilter(toolBar);
|
||||
addSpacer(toolBar, 4);
|
||||
initToolBarFormat(toolBar);
|
||||
addSpacer(toolBar, 4);
|
||||
initToolBarSize(toolBar);
|
||||
addSpacer(toolBar, 4);
|
||||
initToolBarColor(toolBar);
|
||||
addSpacer(toolBar, 4);
|
||||
toolBar->addSeparator();
|
||||
initToolBarSettings(toolBar);
|
||||
}
|
||||
|
||||
void MainWindow::initToolBarActions(QToolBar *toolBar)
|
||||
{
|
||||
m_actions.openPath = toolBar->addAction(materialIcon("folder_open.svg"),
|
||||
tr("Open Path"),
|
||||
this,
|
||||
&MainWindow::openPath);
|
||||
|
||||
m_actions.openFileLocation = toolBar->addAction(materialIcon("share_location.svg"),
|
||||
tr("Open File Location"),
|
||||
this,
|
||||
&MainWindow::openFileLocation);
|
||||
toolBar->addSeparator();
|
||||
m_actions.saveAs = toolBar->addAction(materialIcon("exit_to_app.svg"),
|
||||
tr("Save As..."),
|
||||
this,
|
||||
&MainWindow::saveAs);
|
||||
m_actions.copyFullPath = toolBar->addAction(materialIcon("file_copy.svg"),
|
||||
tr("Copy Full Path"),
|
||||
this,
|
||||
&MainWindow::copyFullPath);
|
||||
m_actions.copyFileName = toolBar->addAction(materialIcon("copy_all.svg"),
|
||||
tr("Copy File Name"),
|
||||
this,
|
||||
&MainWindow::copyFileName);
|
||||
}
|
||||
|
||||
void MainWindow::initToolBarFilter(QToolBar *toolBar)
|
||||
{
|
||||
toolBar->addWidget(new QLabel(tr("Filter\nText")));
|
||||
addSpacer(toolBar, 4);
|
||||
m_searchLineEdit = new QLineEdit(this);
|
||||
m_searchLineEdit->setMinimumWidth(200);
|
||||
m_searchLineEdit->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Fixed);
|
||||
m_searchLineEdit->setClearButtonEnabled(true);
|
||||
toolBar->addWidget(m_searchLineEdit);
|
||||
addSpacer(toolBar, 4);
|
||||
|
||||
QString text = g_xTools.settings()->value(m_settingKeys.filter).toString();
|
||||
m_searchLineEdit->setText(text);
|
||||
|
||||
connect(m_searchLineEdit, &QLineEdit::textEdited, this, [this]() {
|
||||
g_xTools.settings()->setValue(m_settingKeys.filter, m_searchLineEdit->text().trimmed());
|
||||
this->updateView();
|
||||
});
|
||||
}
|
||||
|
||||
void MainWindow::initToolBarFormat(QToolBar *toolBar)
|
||||
{
|
||||
toolBar->addWidget(new QLabel(tr("Export\nFormat")));
|
||||
addSpacer(toolBar, 4);
|
||||
m_formatComboBox = new QComboBox(this);
|
||||
m_formatComboBox->setMinimumWidth(100);
|
||||
m_formatComboBox->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Fixed);
|
||||
toolBar->addWidget(m_formatComboBox);
|
||||
m_formatComboBox->addItems(QStringList() << "SVG"
|
||||
<< "PNG"
|
||||
<< "XPM"
|
||||
<< "ICNS"
|
||||
<< "ICO"
|
||||
<< "TIFF"
|
||||
<< "WEBP");
|
||||
|
||||
QString format = g_xTools.settings()->value(m_settingKeys.format).toString();
|
||||
m_formatComboBox->setCurrentText(format);
|
||||
|
||||
connect(m_formatComboBox, QOverload<int>::of(&QComboBox::activated), this, [this]() {
|
||||
g_xTools.settings()->setValue(m_settingKeys.format, m_formatComboBox->currentText());
|
||||
});
|
||||
}
|
||||
|
||||
void MainWindow::initToolBarSize(QToolBar *toolBar)
|
||||
{
|
||||
toolBar->addWidget(new QLabel(tr("Icon\nSize")));
|
||||
addSpacer(toolBar, 4);
|
||||
m_sizeComboBox = new QComboBox(this);
|
||||
m_sizeComboBox->setMinimumWidth(100);
|
||||
toolBar->addWidget(m_sizeComboBox);
|
||||
m_sizeComboBox->addItems(QStringList() << "16"
|
||||
<< "24"
|
||||
<< "32"
|
||||
<< "48"
|
||||
<< "64"
|
||||
<< "128"
|
||||
<< "256"
|
||||
<< "512");
|
||||
|
||||
QString size = g_xTools.settings()->value(m_settingKeys.size).toString();
|
||||
m_sizeComboBox->setCurrentText(size);
|
||||
SvgItemDelegate::setSize(size.toInt());
|
||||
|
||||
connect(m_sizeComboBox, QOverload<int>::of(&QComboBox::activated), this, [this]() {
|
||||
g_xTools.settings()->setValue(m_settingKeys.size, m_sizeComboBox->currentText());
|
||||
SvgItemDelegate::setSize(m_sizeComboBox->currentText().toInt());
|
||||
updateView();
|
||||
});
|
||||
}
|
||||
|
||||
void MainWindow::initToolBarColor(QToolBar *toolBar)
|
||||
{
|
||||
toolBar->addWidget(new QLabel(tr("Fill\nColor")));
|
||||
addSpacer(toolBar, 4);
|
||||
m_colorButton = new QPushButton(this);
|
||||
m_colorButton->setMinimumWidth(100);
|
||||
m_colorButton->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Fixed);
|
||||
toolBar->addWidget(m_colorButton);
|
||||
|
||||
QString color = g_xTools.settings()->value(m_settingKeys.color).toString();
|
||||
SvgItemDelegate::setColor(color);
|
||||
if (color.isEmpty()) {
|
||||
m_colorButton->setStyleSheet(QString("background-color:%1").arg("#00000000"));
|
||||
} else {
|
||||
m_colorButton->setStyleSheet(QString("background-color:%1").arg(color));
|
||||
}
|
||||
|
||||
connect(m_colorButton, &QPushButton::clicked, this, [this]() {
|
||||
QColor color = QColorDialog::getColor(Qt::white, this, tr("Select Color"));
|
||||
if (!color.isValid()) {
|
||||
SvgItemDelegate::setColor("");
|
||||
g_xTools.settings()->setValue(m_settingKeys.color, "");
|
||||
m_colorButton->setStyleSheet(QString("background-color:#00000000"));
|
||||
} else {
|
||||
SvgItemDelegate::setColor(color.name());
|
||||
g_xTools.settings()->setValue(m_settingKeys.color, color.name());
|
||||
m_colorButton->setStyleSheet(QString("background-color:%1").arg(color.name()));
|
||||
}
|
||||
|
||||
updateView();
|
||||
});
|
||||
}
|
||||
|
||||
void MainWindow::initToolBarSettings(QToolBar *toolBar)
|
||||
{
|
||||
m_settingsMenu = new SettingsMenu(this);
|
||||
QWidgetAction *action = new QWidgetAction(this);
|
||||
action->setDefaultWidget(m_settingsMenu);
|
||||
|
||||
QMenu *menu = new QMenu(this);
|
||||
menu->setIcon(materialIcon("settings.svg"));
|
||||
menu->addAction(action);
|
||||
toolBar->addAction(menu->menuAction());
|
||||
}
|
||||
|
||||
void MainWindow::openPath()
|
||||
{
|
||||
QString path = g_xTools.settings()->value(m_settingKeys.path).toString();
|
||||
path = QFileDialog::getExistingDirectory(this, tr("Open SVG Path"), path);
|
||||
if (path.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
m_path = path;
|
||||
g_xTools.settings()->setValue(m_settingKeys.path, path);
|
||||
updateView();
|
||||
}
|
||||
|
||||
void MainWindow::openFileLocation()
|
||||
{
|
||||
QModelIndexList list = ui->tableView->selectionModel()->selectedIndexes();
|
||||
if (list.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
QStringList pathList;
|
||||
for (const QModelIndex &index : list) {
|
||||
QString fileName = m_model->data(index, Qt::DisplayRole).toString();
|
||||
QString filePath = fileName.left(fileName.lastIndexOf('/'));
|
||||
pathList.append(filePath);
|
||||
}
|
||||
|
||||
pathList.removeDuplicates();
|
||||
for (const QString &path : pathList) {
|
||||
QDesktopServices::openUrl(QUrl::fromLocalFile(path));
|
||||
}
|
||||
}
|
||||
|
||||
void MainWindow::copyTo(const QModelIndexList &list, const QString &path)
|
||||
{
|
||||
for (const QModelIndex &index : list) {
|
||||
QString oldName = m_model->data(index, Qt::DisplayRole).toString();
|
||||
int lastIndexOf = oldName.lastIndexOf('/');
|
||||
QString newName = path + "/" + oldName.right(oldName.length() - lastIndexOf);
|
||||
if (QFile::copy(oldName, newName)) {
|
||||
qInfo() << QString("Copy %1 to %2 successfully").arg(oldName, newName);
|
||||
} else {
|
||||
qWarning() << QString("Copy %1 to %2 failed").arg(oldName, newName);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void MainWindow::exportTo(const QModelIndexList &list, const QString &path, int padding)
|
||||
{
|
||||
for (const QModelIndex &index : list) {
|
||||
QString fileName = m_model->data(index, Qt::DisplayRole).toString();
|
||||
QPixmap pixmap(fileName);
|
||||
if (pixmap.isNull()) {
|
||||
qWarning() << QString("Load %1 failed").arg(fileName);
|
||||
continue;
|
||||
}
|
||||
|
||||
int size = m_sizeComboBox->currentText().toInt();
|
||||
pixmap = pixmap.scaled(QSize(size, size), Qt::KeepAspectRatio, Qt::SmoothTransformation);
|
||||
QUrl url(fileName);
|
||||
QString newFileName = url.fileName();
|
||||
newFileName = newFileName.left(newFileName.lastIndexOf('.'));
|
||||
newFileName = path + "/" + newFileName;
|
||||
|
||||
if (padding > 0) {
|
||||
QPixmap newPixmap(size, size);
|
||||
newPixmap.fill(Qt::transparent);
|
||||
QPainter painter(&newPixmap);
|
||||
auto cookedPadding = QMargins(padding, padding, padding, padding);
|
||||
painter.drawPixmap(newPixmap.rect() - cookedPadding, pixmap);
|
||||
}
|
||||
|
||||
#if 1
|
||||
QString fullPath = newFileName + "." + m_formatComboBox->currentText().toLower();
|
||||
if (!pixmap.save(fullPath, m_formatComboBox->currentText().toStdString().c_str())) {
|
||||
qWarning() << QString("Save as %1 failed").arg(fullPath);
|
||||
}
|
||||
#else
|
||||
// Save all formats for testing...
|
||||
for (int i = 0; i < m_formatComboBox->count(); ++i) {
|
||||
QString format = m_formatComboBox->itemText(i).toLower();
|
||||
if (!pixmap.save(newFileName + "." + format, format.toStdString().c_str())) {
|
||||
qWarning() << QString("Save as %1 failed").arg(newFileName + "." + format);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
void MainWindow::saveAs()
|
||||
{
|
||||
if (xApp::LicenseManager::singleton().isTrial()) {
|
||||
int ret = QMessageBox::warning(
|
||||
this,
|
||||
tr("Trial Limit"),
|
||||
tr("The operation is not supported by trial edition, please purchase full license."),
|
||||
QMessageBox::Ok | QMessageBox::Cancel);
|
||||
if (ret == QMessageBox::Ok) {
|
||||
purchase();
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
QModelIndexList list = ui->tableView->selectionModel()->selectedIndexes();
|
||||
if (list.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
QString path = QFileDialog::getExistingDirectory(this, tr("Copy to..."), QString());
|
||||
if (path.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (m_formatComboBox->currentText() == "SVG") {
|
||||
copyTo(list, path);
|
||||
} else {
|
||||
if (m_settingsMenu->enablePadding()) {
|
||||
exportTo(list, path, m_settingsMenu->padding());
|
||||
} else {
|
||||
exportTo(list, path);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void MainWindow::copyFullPath()
|
||||
{
|
||||
QModelIndexList list = ui->tableView->selectionModel()->selectedIndexes();
|
||||
if (list.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
QStringList fileNames;
|
||||
for (const QModelIndex &index : list) {
|
||||
QString name = m_model->data(index, Qt::DisplayRole).toString();
|
||||
fileNames.append(name);
|
||||
}
|
||||
|
||||
return qApp->clipboard()->setText(fileNames.join('\n'));
|
||||
}
|
||||
|
||||
void MainWindow::copyFileName()
|
||||
{
|
||||
QModelIndexList list = ui->tableView->selectionModel()->selectedIndexes();
|
||||
if (list.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
QStringList fileNames;
|
||||
for (const QModelIndex &index : list) {
|
||||
QString name = m_model->data(index, Qt::DisplayRole).toString();
|
||||
int lastIndexOf = name.lastIndexOf('/');
|
||||
name = name.right(name.length() - lastIndexOf - 1);
|
||||
fileNames.append(name);
|
||||
}
|
||||
|
||||
return qApp->clipboard()->setText(fileNames.join(' '));
|
||||
}
|
||||
|
||||
void MainWindow::updateView()
|
||||
{
|
||||
if (m_path.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (m_isUpdating) {
|
||||
// 在更新过程中会忽略后续的更新请求,但更新完成后,如果需要跟新,会再次更新
|
||||
m_needUpdateAgain = true;
|
||||
return;
|
||||
}
|
||||
|
||||
m_isUpdating = true;
|
||||
m_needUpdateAgain = false;
|
||||
if (ui->tableView->model()) {
|
||||
ui->tableView->model()->deleteLater();
|
||||
}
|
||||
ui->tableView->setModel(nullptr);
|
||||
|
||||
int column = ui->tableView->width() / m_sizeComboBox->currentText().toInt();
|
||||
m_model = new SvgFileDataModel(column, this);
|
||||
connect(m_model, &SvgFileDataModel::dataReady, this, [this, column]() {
|
||||
this->m_isUpdating = false;
|
||||
if (m_model->svgFiles().isEmpty()) {
|
||||
QMessageBox::warning(this,
|
||||
tr("NO SVG FOUND"),
|
||||
tr("The path you selected has no svg file(s), please selected one "
|
||||
"has svg file(s) then try again"));
|
||||
return;
|
||||
}
|
||||
|
||||
ui->tableView->setModel(m_model);
|
||||
for (int i = 0; i < column; ++i) {
|
||||
ui->tableView->setColumnWidth(i, this->m_sizeComboBox->currentText().toInt());
|
||||
}
|
||||
for (int i = 0; i < m_model->rowCount(); ++i) {
|
||||
ui->tableView->setRowHeight(i, this->m_sizeComboBox->currentText().toInt());
|
||||
}
|
||||
qInfo() << "Update view done, the with of column is "
|
||||
<< this->m_sizeComboBox->currentText().toInt();
|
||||
});
|
||||
m_model->update(m_path, m_searchLineEdit->text().trimmed());
|
||||
}
|
||||
|
||||
} // namespace xSvg
|
||||
90
xapps/xsvg/src/mainwindow.h
Normal file
90
xapps/xsvg/src/mainwindow.h
Normal file
@ -0,0 +1,90 @@
|
||||
/***************************************************************************************************
|
||||
* Copyright 2024 x-tools-author(x-tools@outlook.com). All rights reserved.
|
||||
*
|
||||
* The file is encoded using "utf8 with bom", it is a part of xTools project.
|
||||
*
|
||||
* xTools is licensed according to the terms in the file LICENCE(GPL V3) in the root of the source
|
||||
* code directory.
|
||||
**************************************************************************************************/
|
||||
#pragma once
|
||||
|
||||
#include <atomic>
|
||||
|
||||
#include <QModelIndexList>
|
||||
|
||||
#include "xApp/Source/MainWindow.h"
|
||||
|
||||
namespace Ui {
|
||||
class MainWindow;
|
||||
}
|
||||
|
||||
class SettingsMenu;
|
||||
class SvgFileDataModel;
|
||||
|
||||
namespace xSvg {
|
||||
|
||||
class MainWindow : public xApp::MainWindow
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
explicit MainWindow(QWidget* parent = Q_NULLPTR);
|
||||
~MainWindow() override;
|
||||
void showTips();
|
||||
|
||||
protected:
|
||||
bool eventFilter(QObject* obj, QEvent* event) override;
|
||||
|
||||
private:
|
||||
const struct
|
||||
{
|
||||
const QString path = "path";
|
||||
const QString filter = "filter";
|
||||
const QString format = "format";
|
||||
const QString size = "size";
|
||||
const QString color = "color";
|
||||
} m_settingKeys;
|
||||
|
||||
private:
|
||||
Ui::MainWindow* ui;
|
||||
QWidget* m_centralWidget;
|
||||
SvgFileDataModel* m_model{nullptr};
|
||||
QString m_path;
|
||||
std::atomic_bool m_isUpdating{false};
|
||||
std::atomic_bool m_needUpdateAgain{false};
|
||||
SettingsMenu* m_settingsMenu{nullptr};
|
||||
QLineEdit* m_searchLineEdit{nullptr};
|
||||
QComboBox* m_sizeComboBox{nullptr};
|
||||
QComboBox* m_formatComboBox{nullptr};
|
||||
QPushButton* m_colorButton{nullptr};
|
||||
|
||||
struct
|
||||
{
|
||||
QAction* openPath;
|
||||
QAction* openFileLocation;
|
||||
QAction* saveAs;
|
||||
QAction* copyFullPath;
|
||||
QAction* copyFileName;
|
||||
QAction* settingsAction;
|
||||
} m_actions;
|
||||
|
||||
private:
|
||||
void initMenuBar();
|
||||
void initToolBar();
|
||||
void initToolBarActions(QToolBar* toolBar);
|
||||
void initToolBarFilter(QToolBar* toolBar);
|
||||
void initToolBarFormat(QToolBar* toolBar);
|
||||
void initToolBarSize(QToolBar* toolBar);
|
||||
void initToolBarColor(QToolBar* toolBar);
|
||||
void initToolBarSettings(QToolBar* toolBar);
|
||||
|
||||
void openPath();
|
||||
void openFileLocation();
|
||||
void copyTo(const QModelIndexList& list, const QString& path);
|
||||
void exportTo(const QModelIndexList& list, const QString& path, int padding = 0);
|
||||
void saveAs();
|
||||
void copyFullPath();
|
||||
void copyFileName();
|
||||
void updateView();
|
||||
};
|
||||
|
||||
} // namespace xSvg
|
||||
24
xapps/xsvg/src/mainwindow.ui
Normal file
24
xapps/xsvg/src/mainwindow.ui
Normal file
@ -0,0 +1,24 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ui version="4.0">
|
||||
<class>MainWindow</class>
|
||||
<widget class="QWidget" name="MainWindow">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>665</width>
|
||||
<height>295</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
<string>Form</string>
|
||||
</property>
|
||||
<layout class="QGridLayout" name="gridLayout">
|
||||
<item row="0" column="0">
|
||||
<widget class="QTableView" name="tableView"/>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<resources/>
|
||||
<connections/>
|
||||
</ui>
|
||||
50
xapps/xsvg/src/settingsmenu.cpp
Normal file
50
xapps/xsvg/src/settingsmenu.cpp
Normal file
@ -0,0 +1,50 @@
|
||||
/***************************************************************************************************
|
||||
* Copyright 2024 x-tools-author(x-tools@outlook.com). All rights reserved.
|
||||
*
|
||||
* The file is encoded using "utf8 with bom", it is a part of xTools project.
|
||||
*
|
||||
* xTools is licensed according to the terms in the file LICENCE(GPL V3) in the root of the source
|
||||
* code directory.
|
||||
**************************************************************************************************/
|
||||
#include "SettingsMenu.h"
|
||||
#include "ui_SettingsMenu.h"
|
||||
|
||||
#include "Common/xTools.h"
|
||||
|
||||
SettingsMenu::SettingsMenu(QWidget *parent)
|
||||
: QWidget{parent}
|
||||
, ui{new Ui::SettingsMenu}
|
||||
{
|
||||
ui->setupUi(this);
|
||||
int padding = g_xTools.settings()->value(m_settingKeys.padding, 0).toInt();
|
||||
ui->spinBoxPadding->setValue(padding);
|
||||
connect(ui->spinBoxPadding,
|
||||
QOverload<int>::of(&QSpinBox::valueChanged),
|
||||
this,
|
||||
[this](int value) { g_xTools.settings()->setValue(m_settingKeys.padding, value); });
|
||||
|
||||
bool ret = g_xTools.settings()->value(m_settingKeys.enablePadding, false).toBool();
|
||||
ui->checkBoxEnable->setChecked(ret);
|
||||
#if QT_VERSION >= QT_VERSION_CHECK(6, 7, 0)
|
||||
connect(ui->checkBoxEnable, &QCheckBox::checkStateChanged, this, [this](int state) {
|
||||
#else
|
||||
connect(ui->checkBoxEnable, &QCheckBox::stateChanged, this, [this](int state) {
|
||||
#endif
|
||||
g_xTools.settings()->setValue(m_settingKeys.enablePadding, state == Qt::Checked);
|
||||
});
|
||||
}
|
||||
|
||||
SettingsMenu::~SettingsMenu()
|
||||
{
|
||||
delete ui;
|
||||
}
|
||||
|
||||
bool SettingsMenu::enablePadding()
|
||||
{
|
||||
return ui->checkBoxEnable->isChecked();
|
||||
}
|
||||
|
||||
int SettingsMenu::padding()
|
||||
{
|
||||
return ui->spinBoxPadding->value();
|
||||
}
|
||||
36
xapps/xsvg/src/settingsmenu.h
Normal file
36
xapps/xsvg/src/settingsmenu.h
Normal file
@ -0,0 +1,36 @@
|
||||
/***************************************************************************************************
|
||||
* Copyright 2024 x-tools-author(x-tools@outlook.com). All rights reserved.
|
||||
*
|
||||
* The file is encoded using "utf8 with bom", it is a part of xTools project.
|
||||
*
|
||||
* xTools is licensed according to the terms in the file LICENCE(GPL V3) in the root of the source
|
||||
* code directory.
|
||||
**************************************************************************************************/
|
||||
#pragma once
|
||||
|
||||
#include <QWidget>
|
||||
|
||||
namespace Ui {
|
||||
class SettingsMenu;
|
||||
}
|
||||
|
||||
class SettingsMenu : public QWidget
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
explicit SettingsMenu(QWidget *parent = nullptr);
|
||||
~SettingsMenu();
|
||||
|
||||
bool enablePadding();
|
||||
int padding();
|
||||
|
||||
private:
|
||||
const struct
|
||||
{
|
||||
const QString enablePadding = "enablePadding";
|
||||
const QString padding = "padding";
|
||||
} m_settingKeys;
|
||||
|
||||
private:
|
||||
Ui::SettingsMenu *ui;
|
||||
};
|
||||
48
xapps/xsvg/src/settingsmenu.ui
Normal file
48
xapps/xsvg/src/settingsmenu.ui
Normal file
@ -0,0 +1,48 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ui version="4.0">
|
||||
<class>SettingsMenu</class>
|
||||
<widget class="QWidget" name="SettingsMenu">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>200</width>
|
||||
<height>90</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>200</width>
|
||||
<height>0</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
<string notr="true">Form</string>
|
||||
</property>
|
||||
<layout class="QGridLayout" name="gridLayout">
|
||||
<item row="1" column="0">
|
||||
<widget class="QLabel" name="label">
|
||||
<property name="text">
|
||||
<string>Padding</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="0">
|
||||
<widget class="QSpinBox" name="spinBoxPadding">
|
||||
<property name="maximum">
|
||||
<number>496</number>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="0">
|
||||
<widget class="QCheckBox" name="checkBoxEnable">
|
||||
<property name="text">
|
||||
<string>Enable export parameters</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<resources/>
|
||||
<connections/>
|
||||
</ui>
|
||||
96
xapps/xsvg/src/svgfiledatamodel.cpp
Normal file
96
xapps/xsvg/src/svgfiledatamodel.cpp
Normal file
@ -0,0 +1,96 @@
|
||||
/***************************************************************************************************
|
||||
* Copyright 2024 x-tools-author(x-tools@outlook.com). All rights reserved.
|
||||
*
|
||||
* The file is encoded using "utf8 with bom", it is a part of xTools project.
|
||||
*
|
||||
* xTools is licensed according to the terms in the file LICENCE(GPL V3) in the root of the source
|
||||
* code directory.
|
||||
**************************************************************************************************/
|
||||
#include "SvgFileDataModel.h"
|
||||
|
||||
#include <QDir>
|
||||
|
||||
#include "SvgScanner.h"
|
||||
|
||||
SvgFileDataModel::SvgFileDataModel(int column, QObject *parent)
|
||||
: QAbstractTableModel{parent}
|
||||
{
|
||||
m_parameters.column = column;
|
||||
m_scanner = new SvgScanner(this, this);
|
||||
connect(m_scanner, &SvgScanner::finished, this, &SvgFileDataModel::onScannerFinished);
|
||||
}
|
||||
|
||||
void SvgFileDataModel::update(const QString &path, const QString &filter)
|
||||
{
|
||||
m_svgFilesMutex.lock();
|
||||
m_svgFiles.clear();
|
||||
m_svgFilesMutex.unlock();
|
||||
|
||||
m_scanner->didStartScanner(path, filter);
|
||||
}
|
||||
|
||||
void SvgFileDataModel::updateColumn(int column)
|
||||
{
|
||||
m_parameters.column = column;
|
||||
}
|
||||
|
||||
void SvgFileDataModel::updateRecursive(bool recursive)
|
||||
{
|
||||
m_parameters.recursive = recursive;
|
||||
}
|
||||
|
||||
void SvgFileDataModel::updateOverrideColor(const QString &overrideColor)
|
||||
{
|
||||
m_parameters.overrideColor = overrideColor;
|
||||
}
|
||||
|
||||
void SvgFileDataModel::appendSvgFile(const QString &svgFile)
|
||||
{
|
||||
m_svgFilesMutex.lock();
|
||||
m_svgFiles.append(svgFile);
|
||||
m_svgFilesMutex.unlock();
|
||||
}
|
||||
|
||||
QStringList SvgFileDataModel::svgFiles() const
|
||||
{
|
||||
return m_svgFiles;
|
||||
}
|
||||
|
||||
int SvgFileDataModel::rowCount(const QModelIndex &index) const
|
||||
{
|
||||
if (m_svgFiles.isEmpty()) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
int row1 = m_svgFiles.size() / m_parameters.column;
|
||||
int row2 = m_svgFiles.size() % m_parameters.column;
|
||||
return row1 + (row2 > 0 ? 1 : 0);
|
||||
}
|
||||
|
||||
int SvgFileDataModel::columnCount(const QModelIndex &index) const
|
||||
{
|
||||
return m_parameters.column;
|
||||
}
|
||||
|
||||
QVariant SvgFileDataModel::data(const QModelIndex &index, int role) const
|
||||
{
|
||||
int row = index.row();
|
||||
int column = index.column();
|
||||
int listIndex = row * m_parameters.column + column;
|
||||
QString svgFile{"0"};
|
||||
|
||||
m_svgFilesMutex.lock();
|
||||
if (listIndex >= 0 && listIndex < m_svgFiles.size()) {
|
||||
svgFile = m_svgFiles.at(listIndex);
|
||||
}
|
||||
m_svgFilesMutex.unlock();
|
||||
|
||||
return QVariant::fromValue(svgFile);
|
||||
}
|
||||
|
||||
void SvgFileDataModel::onScannerFinished()
|
||||
{
|
||||
auto info = QString("SVG scan finished, row: %1, column: %2").arg(rowCount()).arg(columnCount());
|
||||
qInfo() << qPrintable(info);
|
||||
emit dataReady();
|
||||
}
|
||||
51
xapps/xsvg/src/svgfiledatamodel.h
Normal file
51
xapps/xsvg/src/svgfiledatamodel.h
Normal file
@ -0,0 +1,51 @@
|
||||
/***************************************************************************************************
|
||||
* Copyright 2024 x-tools-author(x-tools@outlook.com). All rights reserved.
|
||||
*
|
||||
* The file is encoded using "utf8 with bom", it is a part of xTools project.
|
||||
*
|
||||
* xTools is licensed according to the terms in the file LICENCE(GPL V3) in the root of the source
|
||||
* code directory.
|
||||
**************************************************************************************************/
|
||||
#pragma once
|
||||
|
||||
#include <QAbstractTableModel>
|
||||
#include <QMutex>
|
||||
#include <QObject>
|
||||
|
||||
class SvgScanner;
|
||||
class SvgFileDataModel : public QAbstractTableModel
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
struct Parameters
|
||||
{
|
||||
bool recursive;
|
||||
int column;
|
||||
QString overrideColor;
|
||||
} m_parameters;
|
||||
|
||||
public:
|
||||
explicit SvgFileDataModel(int column, QObject *parent = nullptr);
|
||||
void update(const QString &path, const QString &filter);
|
||||
void updateColumn(int column);
|
||||
void updateRecursive(bool recursive);
|
||||
void updateOverrideColor(const QString &overrideColor);
|
||||
void appendSvgFile(const QString &svgFile);
|
||||
QStringList svgFiles() const;
|
||||
|
||||
public:
|
||||
int rowCount(const QModelIndex & = QModelIndex()) const override;
|
||||
int columnCount(const QModelIndex & = QModelIndex()) const override;
|
||||
QVariant data(const QModelIndex &index, int role) const override;
|
||||
|
||||
signals:
|
||||
void dataReady();
|
||||
|
||||
private:
|
||||
QStringList m_svgFiles;
|
||||
mutable QMutex m_svgFilesMutex;
|
||||
SvgScanner *m_scanner;
|
||||
|
||||
private:
|
||||
void onScannerFinished();
|
||||
};
|
||||
76
xapps/xsvg/src/svgitemdelegate.cpp
Normal file
76
xapps/xsvg/src/svgitemdelegate.cpp
Normal file
@ -0,0 +1,76 @@
|
||||
/***************************************************************************************************
|
||||
* Copyright 2024 x-tools-author(x-tools@outlook.com). All rights reserved.
|
||||
*
|
||||
* The file is encoded using "utf8 with bom", it is a part of xTools project.
|
||||
*
|
||||
* xTools is licensed according to the terms in the file LICENCE(GPL V3) in the root of the source
|
||||
* code directory.
|
||||
**************************************************************************************************/
|
||||
#include "SvgItemDelegate.h"
|
||||
|
||||
#include <QFile>
|
||||
#include <QPainter>
|
||||
#include <QPushButton>
|
||||
#include <QSvgRenderer>
|
||||
|
||||
QString SvgItemDelegate::s_color;
|
||||
int SvgItemDelegate::s_size{16};
|
||||
SvgItemDelegate::SvgItemDelegate(QObject *parent)
|
||||
: QItemDelegate{parent}
|
||||
{}
|
||||
|
||||
void SvgItemDelegate::paint(QPainter *painter,
|
||||
const QStyleOptionViewItem &option,
|
||||
const QModelIndex &index) const
|
||||
{
|
||||
#if 0
|
||||
QItemDelegate::paint(painter, option, index);
|
||||
#endif
|
||||
|
||||
const QString svgFile = index.data().toString();
|
||||
if (!QFile::exists(svgFile)) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!s_color.isEmpty()) {
|
||||
#if 1
|
||||
QSvgRenderer renderer(svgFile);
|
||||
QImage image(QSize(s_size, s_size), QImage::Format_ARGB32);
|
||||
image.fill(Qt::transparent); // Transparent background
|
||||
|
||||
QPainter tmpPainter(&image);
|
||||
tmpPainter.setRenderHint(QPainter::Antialiasing);
|
||||
renderer.render(&tmpPainter);
|
||||
|
||||
// Change color
|
||||
for (int y = 0; y < image.height(); y++) {
|
||||
for (int x = 0; x < image.width(); x++) {
|
||||
QColor ic = image.pixelColor(x, y);
|
||||
if (ic.alpha() > 0) { // If not transparent
|
||||
image.setPixelColor(x, y, s_color);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
painter->drawPixmap(option.rect, QPixmap::fromImage(image));
|
||||
#else // TODO: This code does not work
|
||||
QSvgRenderer renderer(svgFile);
|
||||
QPixmap pixmap(s_size, s_size);
|
||||
pixmap.fill(Qt::transparent);
|
||||
QPainter tmpPainter(&pixmap);
|
||||
tmpPainter.setRenderHint(QPainter::Antialiasing);
|
||||
tmpPainter.setPen(QPen(QColor(s_color), 1));
|
||||
renderer.render(&tmpPainter);
|
||||
tmpPainter.end();
|
||||
painter->drawPixmap(option.rect, pixmap);
|
||||
#endif
|
||||
} else {
|
||||
const QPixmap pixmap{svgFile};
|
||||
if (pixmap.isNull()) {
|
||||
return;
|
||||
}
|
||||
|
||||
painter->setRenderHints(QPainter::Antialiasing | QPainter::SmoothPixmapTransform);
|
||||
painter->drawPixmap(option.rect, pixmap);
|
||||
}
|
||||
}
|
||||
27
xapps/xsvg/src/svgitemdelegate.h
Normal file
27
xapps/xsvg/src/svgitemdelegate.h
Normal file
@ -0,0 +1,27 @@
|
||||
/***************************************************************************************************
|
||||
* Copyright 2024 x-tools-author(x-tools@outlook.com). All rights reserved.
|
||||
*
|
||||
* The file is encoded using "utf8 with bom", it is a part of xTools project.
|
||||
*
|
||||
* xTools is licensed according to the terms in the file LICENCE(GPL V3) in the root of the source
|
||||
* code directory.
|
||||
**************************************************************************************************/
|
||||
#pragma once
|
||||
|
||||
#include <QItemDelegate>
|
||||
|
||||
class SvgItemDelegate : public QItemDelegate
|
||||
{
|
||||
public:
|
||||
explicit SvgItemDelegate(QObject *parent = nullptr);
|
||||
void paint(QPainter *painter,
|
||||
const QStyleOptionViewItem &option,
|
||||
const QModelIndex &index) const override;
|
||||
|
||||
static void setColor(const QString &color) { s_color = color; }
|
||||
static void setSize(int size) { s_size = size < 16 ? 16 : size; }
|
||||
|
||||
private:
|
||||
static QString s_color;
|
||||
static int s_size;
|
||||
};
|
||||
87
xapps/xsvg/src/svgscanner.cpp
Normal file
87
xapps/xsvg/src/svgscanner.cpp
Normal file
@ -0,0 +1,87 @@
|
||||
/***************************************************************************************************
|
||||
* Copyright 2024 x-tools-author(x-tools@outlook.com). All rights reserved.
|
||||
*
|
||||
* The file is encoded using "utf8 with bom", it is a part of xTools project.
|
||||
*
|
||||
* xTools is licensed according to the terms in the file LICENCE(GPL V3) in the root of the source
|
||||
* code directory.
|
||||
**************************************************************************************************/
|
||||
#include "SvgScanner.h"
|
||||
|
||||
#include <QDir>
|
||||
#include <QTimer>
|
||||
|
||||
#include "SvgFileDataModel.h"
|
||||
|
||||
#if 0
|
||||
#define USING_MULTITHREAD
|
||||
#endif
|
||||
|
||||
SvgScanner::SvgScanner(SvgFileDataModel *model, QObject *parent)
|
||||
: QThread{parent}
|
||||
, m_model{model}
|
||||
{}
|
||||
|
||||
void SvgScanner::didStartScanner(const QString &rootPath, const QString &filter)
|
||||
{
|
||||
if (isRunning()) {
|
||||
return;
|
||||
}
|
||||
|
||||
m_rootPath = rootPath;
|
||||
m_filter = filter;
|
||||
start();
|
||||
}
|
||||
|
||||
void SvgScanner::run()
|
||||
{
|
||||
if (m_rootPath.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
didStartScannerActually(m_rootPath);
|
||||
#if defined(USING_MULTITHREAD)
|
||||
std::this_thread::sleep_for(std::chrono::seconds(1));
|
||||
while (!this->m_threads.isEmpty()) {
|
||||
m_threadsMutex.lock();
|
||||
auto task = this->m_threads.takeFirst();
|
||||
m_threadsMutex.unlock();
|
||||
task->join();
|
||||
delete task;
|
||||
|
||||
m_threadsMutex.lock();
|
||||
if (this->m_threads.isEmpty()) {
|
||||
std::this_thread::sleep_for(std::chrono::seconds(1));
|
||||
}
|
||||
m_threadsMutex.unlock();
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
void SvgScanner::didStartScannerActually(const QString &path)
|
||||
{
|
||||
QDir dir(path);
|
||||
QList<QFileInfo> infos = dir.entryInfoList(QDir::NoDotAndDotDot | QDir::Files | QDir::Dirs
|
||||
| QDir::NoSymLinks);
|
||||
for (auto &info : infos) {
|
||||
if (info.isDir()) {
|
||||
#if defined(USING_MULTITHREAD)
|
||||
qInfo() << info.absoluteFilePath();
|
||||
auto task = new std::thread(&SvgScanner::didStartScannerActually,
|
||||
this,
|
||||
info.absoluteFilePath());
|
||||
m_threadsMutex.lock();
|
||||
m_threads.append(task);
|
||||
m_threadsMutex.unlock();
|
||||
#else
|
||||
didStartScannerActually(info.absoluteFilePath());
|
||||
#endif
|
||||
} else {
|
||||
bool endsWithSvg = info.fileName().endsWith(QString("svg"), Qt::CaseInsensitive);
|
||||
bool hasFilter = info.fileName().contains(m_filter, Qt::CaseInsensitive);
|
||||
if (endsWithSvg && hasFilter) {
|
||||
m_model->appendSvgFile(info.absoluteFilePath());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
38
xapps/xsvg/src/svgscanner.h
Normal file
38
xapps/xsvg/src/svgscanner.h
Normal file
@ -0,0 +1,38 @@
|
||||
/***************************************************************************************************
|
||||
* Copyright 2024 x-tools-author(x-tools@outlook.com). All rights reserved.
|
||||
*
|
||||
* The file is encoded using "utf8 with bom", it is a part of xTools project.
|
||||
*
|
||||
* xTools is licensed according to the terms in the file LICENCE(GPL V3) in the root of the source
|
||||
* code directory.
|
||||
**************************************************************************************************/
|
||||
#pragma once
|
||||
|
||||
#include <thread>
|
||||
|
||||
#include <QMutex>
|
||||
#include <QThread>
|
||||
|
||||
class SvgFileDataModel;
|
||||
class SvgScanner : public QThread
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
explicit SvgScanner(SvgFileDataModel *model, QObject *parent = nullptr);
|
||||
|
||||
void didStartScanner(const QString &rootPath, const QString &filter);
|
||||
|
||||
protected:
|
||||
void run() override;
|
||||
|
||||
private:
|
||||
QString m_rootPath;
|
||||
QString m_filter;
|
||||
QList<std::thread *> m_threads;
|
||||
QMutex m_threadsMutex;
|
||||
|
||||
SvgFileDataModel *m_model;
|
||||
|
||||
private:
|
||||
void didStartScannerActually(const QString &path);
|
||||
};
|
||||
34
xapps/xsvg/xSvg.cmake
Normal file
34
xapps/xsvg/xSvg.cmake
Normal file
@ -0,0 +1,34 @@
|
||||
set(X_SVG_SOURCE ${X_TOOLS_SOURCE})
|
||||
|
||||
file(GLOB X_SVG_SOURCE ${CMAKE_CURRENT_SOURCE_DIR}/Source/*.*)
|
||||
list(APPEND X_SVG_SOURCE ${CMAKE_CURRENT_SOURCE_DIR}/xSvg.rc)
|
||||
list(APPEND X_SVG_SOURCE ${CMAKE_CURRENT_SOURCE_DIR}/xSvg.qrc)
|
||||
|
||||
x_tools_add_executable(xSvg ${X_SVG_SOURCE})
|
||||
x_tools_add_stylesheet_resources(xSvg)
|
||||
x_tools_deploy_qt(xSvg)
|
||||
x_tools_tar_target(xSvg)
|
||||
x_tools_copy_microsoft_store_dll(xSvg)
|
||||
x_tools_get_latest_version_from_tag(xSvg X_SVG_VERSION)
|
||||
|
||||
target_link_libraries(xSvg PRIVATE xApp)
|
||||
|
||||
# --------------------------------------------------------------------------------------------------
|
||||
# Generate installer(exe)
|
||||
set(root_dir "${CMAKE_BINARY_DIR}/installer/xSvg")
|
||||
set(icon ${CMAKE_CURRENT_SOURCE_DIR}/xSvg.ico)
|
||||
x_tools_generate_installer(xSvg xSvg ${X_SVG_VERSION})
|
||||
|
||||
# --------------------------------------------------------------------------------------------------
|
||||
# Generate Microsoft Store package(MSIX)
|
||||
if(WIN32)
|
||||
x_tools_generate_msix(xSvg "xSvg" "xSvg" "${X_SVG_VERSION}" OFF)
|
||||
endif()
|
||||
x_tools_generate_translations(xSvg)
|
||||
|
||||
set_target_properties(xSvg PROPERTIES FOLDER "xSvg")
|
||||
set_target_properties(xSvg_lupdate PROPERTIES FOLDER "xSvg")
|
||||
set_target_properties(xSvg_lrelease PROPERTIES FOLDER "xSvg")
|
||||
set_target_properties(xSvg_lupgrade PROPERTIES FOLDER "xSvg")
|
||||
set_target_properties(xSvg_installer PROPERTIES FOLDER "xSvg")
|
||||
set_target_properties(xSvg_msix PROPERTIES FOLDER "xSvg")
|
||||
BIN
xapps/xsvg/xSvg.ico
Normal file
BIN
xapps/xsvg/xSvg.ico
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 17 KiB |
9
xapps/xsvg/xSvg.md
Normal file
9
xapps/xsvg/xSvg.md
Normal file
@ -0,0 +1,9 @@
|
||||
# xSvg
|
||||
|
||||
xSvg 是一款SVG图片预览工具,有以下亮点:
|
||||
|
||||
- 高效预览:支持巨量SVG图片的快速导入预览,可以选择图片导入,可以指定目录导入
|
||||
- 快速搜索:支持模糊搜索,快速、高效、便捷地找到您想要的图片
|
||||
- 一件配色:可以更改SVG图片的填充颜色,一键生成统一配色的图标
|
||||
- 统一大小:导出为其他格式图片时,可以调整内容边距,统一图标显示效果
|
||||
- 格式转换:可以将SVG转换为以下格式:PNG, XPM, ICNS, ICO, TIFF, WEBP
|
||||
6
xapps/xsvg/xSvg.qrc
Normal file
6
xapps/xsvg/xSvg.qrc
Normal file
@ -0,0 +1,6 @@
|
||||
<RCC>
|
||||
<qresource prefix="/">
|
||||
<file>Resources/Translations/xSvg_en.qm</file>
|
||||
<file>Resources/Translations/xSvg_zh_CN.qm</file>
|
||||
</qresource>
|
||||
</RCC>
|
||||
1
xapps/xsvg/xSvg.rc
Normal file
1
xapps/xsvg/xSvg.rc
Normal file
@ -0,0 +1 @@
|
||||
IDI_ICON1 ICON DISCARDABLE "xSvg.ico"
|
||||
1
xapps/xsvg/xSvg.svg
Normal file
1
xapps/xsvg/xSvg.svg
Normal file
@ -0,0 +1 @@
|
||||
<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1715170296760" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="6057" xmlns:xlink="http://www.w3.org/1999/xlink" width="200" height="200"><path d="M956 686.5l-0.1-0.1-0.1-0.1C911.7 593 843.4 545 752.5 545s-159.2 48.1-203.4 141.3v0.1c-5.4 11.5-5.4 24.9 0 36.4C593.3 816 661.6 864 752.5 864s159.2-48.1 203.4-141.3c5.4-11.5 5.4-24.8 0.1-36.2zM752.5 800c-62.1 0-107.4-30-141.1-95.5C645 639 690.4 609 752.5 609c62.1 0 107.4 30 141.1 95.5C860 770 814.6 800 752.5 800z" p-id="6058" fill="#1296db"></path><path d="M753 705m-56 0a56 56 0 1 0 112 0 56 56 0 1 0-112 0Z" p-id="6059" fill="#1296db"></path><path d="M136 232h704v253h72V192c0-17.7-14.3-32-32-32H96c-17.7 0-32 14.3-32 32v520c0 17.7 14.3 32 32 32h352v-72H136V232z" p-id="6060" fill="#1296db"></path><path d="M724.9 338.1l-36.8-36.8c-3.1-3.1-8.2-3.1-11.3 0L493 485.3l-86.1-86.2c-3.1-3.1-8.2-3.1-11.3 0L251.3 543.4c-3.1 3.1-3.1 8.2 0 11.3l36.8 36.8c3.1 3.1 8.2 3.1 11.3 0l101.8-101.8 86.1 86.2c3.1 3.1 8.2 3.1 11.3 0l226.3-226.5c3.2-3.1 3.2-8.2 0-11.3z" p-id="6061" fill="#1296db"></path></svg>
|
||||
|
After Width: | Height: | Size: 1.2 KiB |
3
xapps/xsvg/xSvg.txt
Normal file
3
xapps/xsvg/xSvg.txt
Normal file
@ -0,0 +1,3 @@
|
||||
|
||||
2024年5月6日 11:48:25
|
||||
|
||||
Loading…
Reference in New Issue
Block a user