diff --git a/.github/workflows/qt-build-test.yml b/.github/workflows/qt-build-test.yml
index 1161300..b214483 100644
--- a/.github/workflows/qt-build-test.yml
+++ b/.github/workflows/qt-build-test.yml
@@ -11,9 +11,14 @@ jobs:
strategy:
matrix:
- os: [ubuntu-latest]
+ os: [windows-latest, ubuntu-latest]
qt_version: [5.15.2, 6.6.2]
- arch: [gcc_64]
+ arch: [win64_msvc2019_64, gcc_64]
+ exclude:
+ - os: windows-latest
+ arch: gcc_64
+ - os: ubuntu-latest
+ arch: win64_msvc2019_64
steps:
- uses: actions/checkout@v3
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 02db5d5..b0a66e3 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -200,8 +200,15 @@ else()
endif()
if(${QT_VERSION_MAJOR} GREATER_EQUAL 6)
- qt_add_executable(WingGifEditor2 MANUAL_FINALIZATION ${PROJECT_SOURCES}
- ${QM_FILES})
+ if(WIN32)
+ set(app_icon_resource_windows "${CMAKE_CURRENT_SOURCE_DIR}/favicon.rc")
+ qt_add_executable(WingGifEditor2 MANUAL_FINALIZATION ${PROJECT_SOURCES}
+ ${QM_FILES} ${app_icon_resource_windows})
+ else()
+ qt_add_executable(WingGifEditor2 MANUAL_FINALIZATION ${PROJECT_SOURCES}
+ ${QM_FILES})
+ endif()
+
# Define target properties for Android with Qt 6 as: set_property(TARGET
# WingGifEditor2 APPEND PROPERTY QT_ANDROID_PACKAGE_SOURCE_DIR
# ${CMAKE_CURRENT_SOURCE_DIR}/android) For more information, see
@@ -210,7 +217,14 @@ else()
if(ANDROID)
message(FATAL_ERROR "Not supported for Android!")
else()
- add_executable(WingGifEditor2 ${PROJECT_SOURCES} ${QM_FILES})
+ if(WIN32)
+ set(app_icon_resource_windows
+ "${CMAKE_CURRENT_SOURCE_DIR}/favicon.rc")
+ add_executable(WingGifEditor2 ${PROJECT_SOURCES} ${QM_FILES}
+ ${app_icon_resource_windows})
+ else()
+ add_executable(WingGifEditor2 ${PROJECT_SOURCES} ${QM_FILES})
+ endif()
endif()
endif()
diff --git a/appicon.ico b/appicon.ico
new file mode 100644
index 0000000..1e0d150
Binary files /dev/null and b/appicon.ico differ
diff --git a/favicon.rc b/favicon.rc
new file mode 100644
index 0000000..17cc6d7
--- /dev/null
+++ b/favicon.rc
@@ -0,0 +1,3 @@
+// Icon with lowest ID value placed first to ensure application icon
+// remains consistent on all systems.
+IDI_ICON1 ICON "appicon.ico"
\ No newline at end of file
diff --git a/lang/WingGifEditor2_zh_CN.ts b/lang/WingGifEditor2_zh_CN.ts
index 350d3b3..3d7815c 100644
--- a/lang/WingGifEditor2_zh_CN.ts
+++ b/lang/WingGifEditor2_zh_CN.ts
@@ -5,6 +5,7 @@
AboutSoftwareDialog
+
关于
@@ -233,7 +234,7 @@
LanguageManager
-
+
中文(简体)
@@ -299,48 +300,48 @@
MainWindow
-
+
是否保存
-
+
羽云 GIF 编辑器
-
+
文件
-
+
编辑
-
+
视图
-
+
插件
-
+
设置
-
+
关于
-
-
+
+
@@ -349,81 +350,81 @@
选择文件
-
+
选择文件以打开
-
+
从图像序列创建动图
-
+
无效 GIF 文件
-
+
保存 GIF
-
-
+
+
被用户取消操作
-
+
保存成功
-
+
保存失败
-
+
选择保存文件路径
-
+
另存为 GIF
-
+
另存为成功
-
+
另存为失败
-
+
导出帧
-
+
导出成功
-
+
导出失败
-
+
跳转
@@ -465,7 +466,7 @@
-
+
插入图片序列
@@ -495,325 +496,355 @@
无效模型
-
+
基础
-
+
从图序新建
-
+
从动图创建
-
+
打开
-
+
+
+ 关闭
+
+
+
最近文件
-
-
+
+
+ 从动图创建中
+
+
+
+
保存
-
+
另存为
-
+
导出
-
+
文件信息
-
-
+
+
基本
-
+
撤销
-
+
重做
-
+
剪切
-
+
复制
-
+
粘贴
-
+
删除
-
+
帧
-
+
降低帧率
-
+
删除之前帧
-
+
删除之后帧
-
+
左移帧
-
+
右移帧
-
+
反转
-
+
设置延时
-
+
图像
-
+
缩放 GIF
-
+
裁切 GIF
-
+
水平反转
-
+
垂直翻转
-
+
逆时针旋转
-
+
顺时针旋转
-
+
效果
-
+
导出模板
-
+
应用模型
-
+
创建逆向帧动画
-
+
缩放延时
-
+
合并
-
+
合并动图
-
+
播放
-
+
第一帧
-
+
上一帧
-
+
播放
-
+
停止
-
+
下一帧
-
+
最后帧
-
+
查找
-
+
+
+ 适合编辑区
+
+
+
全选
-
+
取消选择
-
+
反选
-
+
日志
-
+
信息
-
+
缩放
-
+
插件信息
-
+
设置
-
+
软件
-
+
赞助
-
+
WIKI
-
+
关于 QT
-
+
+
+ 读取 GIF 中
+
+
+
+
+ 写入 GIF 中
+
+
+
+
+ 导出 GIF 中
+
+
+
确认退出
-
+
你确认未保存就退出软件吗?
-
+
未命名
-
+
帧:%1/%2
-
+
新帧
-
+
请设置新帧延时(时间只保留十位)
@@ -1088,7 +1119,7 @@
WaitingLoop
-
+
请等待
diff --git a/src/class/gifcontentmodel.cpp b/src/class/gifcontentmodel.cpp
index 7055680..3f6d19e 100644
--- a/src/class/gifcontentmodel.cpp
+++ b/src/class/gifcontentmodel.cpp
@@ -1,5 +1,9 @@
#include "gifcontentmodel.h"
+#ifdef Q_OS_WIN
+#include
+#endif
+
GifContentModel::GifContentModel(QObject *parent)
: QAbstractListModel(parent) {}
@@ -209,10 +213,16 @@ void GifContentModel::cropFrames(const QRect &rect) {
}
Q_ASSERT(_data.first().rect().contains(rect));
+#ifdef Q_OS_WIN
+ concurrency::parallel_for_each(
+ _data.begin(), _data.end(),
+ [rect](QImage &img) { img = img.copy(rect); });
+#else
#pragma omp parallel for
for (auto &img : _data) {
img = img.copy(rect);
}
+#endif
emit dataChanged(this->index(0), this->index(_data.size() - 1));
updateLinkedListViewCurrent();
@@ -261,11 +271,19 @@ void GifContentModel::scaleFrames(int width, int height) {
return;
}
+#ifdef Q_OS_WIN
+ concurrency::parallel_for_each(
+ _data.begin(), _data.end(), [width, height](QImage &img) {
+ img = img.scaled(width, height, Qt::IgnoreAspectRatio,
+ Qt::SmoothTransformation);
+ });
+#else
#pragma omp parallel for
for (auto &img : _data) {
img = img.scaled(width, height, Qt::IgnoreAspectRatio,
Qt::SmoothTransformation);
}
+#endif
emit dataChanged(this->index(0), this->index(_data.size() - 1));
updateLinkedListViewCurrent();
@@ -275,17 +293,29 @@ void GifContentModel::flipFrames(Qt::Orientation dir, int index,
qsizetype count) {
switch (dir) {
case Qt::Horizontal: {
+#ifdef Q_OS_WIN
+ concurrency::parallel_for_each(
+ _data.begin(), _data.end(),
+ [](QImage &img) { img = img.mirrored(true, false); });
+#else
#pragma omp parallel for
for (auto &img : _data) {
img = img.mirrored(true, false);
}
+#endif
break;
}
case Qt::Vertical: {
+#ifdef Q_OS_WIN
+ concurrency::parallel_for_each(
+ _data.begin(), _data.end(),
+ [](QImage &img) { img = img.mirrored(); });
+#else
#pragma omp parallel for
for (auto &img : _data) {
img = img.mirrored();
}
+#endif
break;
}
}
@@ -313,10 +343,19 @@ void GifContentModel::reverseFrames(qsizetype begin, qsizetype end) {
void GifContentModel::rotateFrames(bool clockwise) {
QTransform trans;
trans.rotate(clockwise ? -90 : 90);
+
+#ifdef Q_OS_WIN
+ concurrency::parallel_for_each(
+ _data.begin(), _data.end(), [&trans](QImage &img) {
+ img = img.transformed(trans, Qt::SmoothTransformation);
+ });
+#else
#pragma omp parallel for
for (auto &img : _data) {
img = img.transformed(trans, Qt::SmoothTransformation);
}
+#endif
+
emit dataChanged(this->index(0), this->index(_data.size() - 1));
updateLinkedListViewCurrent();
}
diff --git a/src/class/gifreader.cpp b/src/class/gifreader.cpp
index 0af7d89..5ac043f 100644
--- a/src/class/gifreader.cpp
+++ b/src/class/gifreader.cpp
@@ -3,7 +3,8 @@
#include
#include
-GifReader::GifReader(const QString &filename) {
+GifReader::GifReader(const QString &filename, QObject *parent)
+ : QObject(parent) {
if (QFile::exists(filename)) {
load(filename);
}
@@ -161,6 +162,8 @@ bool GifReader::load(const QString &filename) {
default:
break;
}
+
+ emit sigUpdateUIProcess();
} while (recordType != TERMINATE_RECORD_TYPE);
return closeHandle(handle);
diff --git a/src/class/gifreader.h b/src/class/gifreader.h
index 0ed1a5c..a61ebff 100644
--- a/src/class/gifreader.h
+++ b/src/class/gifreader.h
@@ -4,12 +4,16 @@
#include "giflib/gif_lib.h"
#include
+#include
#include
#include
-class GifReader {
+class GifReader : public QObject {
+ Q_OBJECT
+
public:
- explicit GifReader(const QString &filename = QString());
+ explicit GifReader(const QString &filename = QString(),
+ QObject *parent = nullptr);
virtual ~GifReader();
@@ -33,6 +37,9 @@ class GifReader {
QString comment() const;
+signals:
+ void sigUpdateUIProcess();
+
private:
bool closeHandleWithError(GifFileType *handle);
diff --git a/src/class/gifwriter.cpp b/src/class/gifwriter.cpp
index c8ec574..370597b 100644
--- a/src/class/gifwriter.cpp
+++ b/src/class/gifwriter.cpp
@@ -2,8 +2,9 @@
#include
-GifWriter::GifWriter(int width, int height, const QString &filename)
- : m_width(width), m_height(height), m_filename(filename) {
+GifWriter::GifWriter(int width, int height, const QString &filename,
+ QObject *parent)
+ : QObject(parent), m_width(width), m_height(height), m_filename(filename) {
Q_ASSERT(width > 0 && height > 0);
}
@@ -98,6 +99,8 @@ bool GifWriter::save(const QString &filename, unsigned int loopCount) {
if (!addFrame(handle, key, key.rect(), m_delays.at(0), resources))
return closeEHandleWithError(handle);
+ emit sigUpdateUIProcess();
+
int delta = 0;
for (qsizetype i = 1; i < m_data.size(); ++i) {
@@ -108,6 +111,8 @@ bool GifWriter::save(const QString &filename, unsigned int loopCount) {
if (!result)
return closeEHandleWithError(handle);
+
+ emit sigUpdateUIProcess();
}
closeEHandle(handle);
diff --git a/src/class/gifwriter.h b/src/class/gifwriter.h
index 10b4538..0dbacd5 100644
--- a/src/class/gifwriter.h
+++ b/src/class/gifwriter.h
@@ -5,11 +5,13 @@
#include
#include
+#include
#include
#include
-class GifWriter {
+class GifWriter : public QObject {
+ Q_OBJECT
private:
struct Color {
unsigned char red = 0;
@@ -280,7 +282,8 @@ class GifWriter {
public:
explicit GifWriter(int width, int height,
- const QString &filename = QString());
+ const QString &filename = QString(),
+ QObject *parent = nullptr);
void push(const QImage &img, int delay);
@@ -306,6 +309,9 @@ class GifWriter {
void setExtString(const QString &newExtString);
+signals:
+ void sigUpdateUIProcess();
+
private:
bool closeEHandle(GifFileType *handle);
diff --git a/src/class/languagemanager.cpp b/src/class/languagemanager.cpp
index 1d2930a..e037a14 100644
--- a/src/class/languagemanager.cpp
+++ b/src/class/languagemanager.cpp
@@ -3,6 +3,7 @@
#include
#include
#include
+#include
#include
LanguageManager &LanguageManager::instance() {
@@ -33,6 +34,28 @@ LanguageManager::LanguageManager() {
}
_defaultLocale = QLocale::system();
+
+ if (m_langs.isEmpty()) {
+#if QT_VERSION > QT_VERSION_CHECK(6, 0, 0)
+ if (QLocale::China == _defaultLocale.territory()
+#else
+ if (QLocale::China == _defaultLocale.country()
+#endif
+ ) {
+ QMessageBox::critical(
+ nullptr, QStringLiteral("程序损坏"),
+ QStringLiteral(
+ "语言文件已损坏,请尝试重装软件以解决这个问题。"));
+ } else {
+ QMessageBox::critical(
+ nullptr, QStringLiteral("Corruption"),
+ QStringLiteral("The language file has been damaged. "
+ "Please try reinstalling the software to "
+ "solve the problem."));
+ }
+ qApp->exit(-1);
+ }
+
bool found = false;
for (auto p = m_localeMap.begin(); p != m_localeMap.end(); ++p) {
#if QT_VERSION > QT_VERSION_CHECK(6, 0, 0)
diff --git a/src/class/waitingloop.cpp b/src/class/waitingloop.cpp
index f2b719c..9bf5aa0 100644
--- a/src/class/waitingloop.cpp
+++ b/src/class/waitingloop.cpp
@@ -1,5 +1,7 @@
#include "waitingloop.h"
+#include
+
WaitingLoop::WaitingLoop(const QString &tip) {
dw.dialog()->setCancelButton(nullptr);
dw.dialog()->setLabelText(tip);
diff --git a/src/class/waitingloop.h b/src/class/waitingloop.h
index aa7d058..55500aa 100644
--- a/src/class/waitingloop.h
+++ b/src/class/waitingloop.h
@@ -5,6 +5,7 @@
#include
#include
+#include
class WaitingLoop : public QObject {
Q_OBJECT
diff --git a/src/control/gifeditor.cpp b/src/control/gifeditor.cpp
index 5e4ad75..c2c1ed7 100644
--- a/src/control/gifeditor.cpp
+++ b/src/control/gifeditor.cpp
@@ -13,6 +13,22 @@ GifEditor::GifEditor(const QImage &img, QWidget *parent)
void GifEditor::setImage(const QImage &img) { scene->setFrameImg(img); }
+void GifEditor::fitOpenSize() {
+ auto imgSize = scene->frameImageSize();
+ auto wSize = this->size();
+ if (imgSize.width() > wSize.width() || imgSize.height() > wSize.height()) {
+ fitInEditorView();
+ } else {
+ resetTransform();
+ }
+}
+
+void GifEditor::fitInEditorView() {
+ auto r = scene->contentBounding();
+ setSceneRect(r);
+ fitInView(r, Qt::KeepAspectRatio);
+}
+
void GifEditor::setCropMode(bool b) { scene->setCuttingMode(b); }
void GifEditor::zoomIn() { scale(1.1, 1.1); }
diff --git a/src/control/gifeditor.h b/src/control/gifeditor.h
index 71a2b2f..395aec8 100644
--- a/src/control/gifeditor.h
+++ b/src/control/gifeditor.h
@@ -12,17 +12,20 @@ class GifEditor : public QGraphicsView {
GifEditor(const QImage &img, QWidget *parent = nullptr);
void setImage(const QImage &img);
+ QRectF selRect() const;
+
+public slots:
+ void setSelRect(int x, int y, int w, int h);
+ void fitOpenSize();
+
+ void fitInEditorView();
+
void setCropMode(bool b);
void zoomIn();
void zoomOut();
void setZoom(int value);
- QRectF selRect() const;
-
-public slots:
- void setSelRect(int x, int y, int w, int h);
-
signals:
void selRectChanged(QRectF rect);
diff --git a/src/control/gifeditorscene.cpp b/src/control/gifeditorscene.cpp
index 07b4af5..eb128b2 100644
--- a/src/control/gifeditorscene.cpp
+++ b/src/control/gifeditorscene.cpp
@@ -9,14 +9,14 @@ GifEditorScene::GifEditorScene(const QImage &img, QObject *parent)
sel->setBackgroundColor(Qt::transparent);
sel->setCropperVisible(false);
sel->setImage(img);
- auto w = addWidget(sel);
- connect(sel, &ImageCropper::sizeChanged, w, [=] {
+ gw = addWidget(sel);
+ connect(sel, &ImageCropper::sizeChanged, gw, [=] {
// call the internal updateProxyGeometryFromWidget
- w->resetTransform();
- w->setWidget(nullptr);
- w->setWidget(sel);
+ gw->resetTransform();
+ gw->setWidget(nullptr);
+ gw->setWidget(sel);
// center the image
- setSceneRect(QRectF(QPointF(), w->size()));
+ setSceneRect(QRectF(QPointF(), gw->size()));
});
connect(sel, &ImageCropper::selRectChanged, this,
&GifEditorScene::selRectChanged);
@@ -32,6 +32,10 @@ void GifEditorScene::setCuttingMode(bool value) {
void GifEditorScene::setFrameImg(const QImage &img) { sel->setImage(img); }
+QRectF GifEditorScene::contentBounding() const { return gw->boundingRect(); }
+
+QSize GifEditorScene::frameImageSize() const { return sel->imageSize(); }
+
QRectF GifEditorScene::selRect() const { return sel->selRect(); }
void GifEditorScene::setSelRect(int x, int y, int w, int h) {
diff --git a/src/control/gifeditorscene.h b/src/control/gifeditorscene.h
index e59c80e..a47df2a 100644
--- a/src/control/gifeditorscene.h
+++ b/src/control/gifeditorscene.h
@@ -15,6 +15,10 @@ class GifEditorScene : public QGraphicsScene {
void setFrameImg(const QImage &img);
+ QRectF contentBounding() const;
+
+ QSize frameImageSize() const;
+
QRectF selRect() const;
public slots:
@@ -26,6 +30,7 @@ public slots:
private:
ImageCropper *sel;
QPointF oldpos;
+ QGraphicsProxyWidget *gw;
};
#endif // GIFEDITORSCENE_H
diff --git a/src/control/imagecropper/imagecropper.cpp b/src/control/imagecropper/imagecropper.cpp
index 819f626..f96e98f 100644
--- a/src/control/imagecropper/imagecropper.cpp
+++ b/src/control/imagecropper/imagecropper.cpp
@@ -26,6 +26,8 @@ bool ImageCropper::proportionFixed() const { return pimpl->isProportionFixed; }
QRectF ImageCropper::selRect() const { return pimpl->croppingRect; }
+QSize ImageCropper::imageSize() const { return pimpl->imageForCropping.size(); }
+
void ImageCropper::setSelRect(int x, int y, int w, int h) {
if (pimpl->isProportionFixed) {
pimpl->croppingRect = QRectF(
diff --git a/src/control/imagecropper/imagecropper.h b/src/control/imagecropper/imagecropper.h
index 2f20c93..8f39909 100644
--- a/src/control/imagecropper/imagecropper.h
+++ b/src/control/imagecropper/imagecropper.h
@@ -20,6 +20,8 @@ class ImageCropper : public QWidget {
QRectF selRect() const;
+ QSize imageSize() const;
+
void setSelRect(int x, int y, int w, int h);
public slots:
diff --git a/src/dialog/aboutsoftwaredialog.cpp b/src/dialog/aboutsoftwaredialog.cpp
index 759d574..04b6f23 100644
--- a/src/dialog/aboutsoftwaredialog.cpp
+++ b/src/dialog/aboutsoftwaredialog.cpp
@@ -13,6 +13,8 @@ AboutSoftwareDialog::AboutSoftwareDialog(QWidget *parent)
ui->lblVersion->setText(WINGGIF_VERSION);
+ _dialog->setWindowTitle(tr("About"));
+
Utilities::moveToCenter(this);
}
diff --git a/src/dialog/mainwindow.cpp b/src/dialog/mainwindow.cpp
index 4aa9205..a798030 100644
--- a/src/dialog/mainwindow.cpp
+++ b/src/dialog/mainwindow.cpp
@@ -1,5 +1,6 @@
#include "mainwindow.h"
+#include
#include
#include
@@ -121,6 +122,19 @@ MainWindow::MainWindow(QWidget *parent) : FramelessMainWindow(parent) {
connect(_player, &PlayGifManager::playStateChanged, this,
&MainWindow::updatePlayState);
+ auto psc = new QShortcut(QKeySequence(Qt::Key_Space), this);
+ psc->setContext(Qt::ShortcutContext::WindowShortcut);
+ connect(psc, &QShortcut::activated, this, [=] {
+ if (_curfilename.isEmpty()) {
+ return;
+ }
+ if (_player->isPlaying()) {
+ on_stop();
+ } else {
+ on_play();
+ }
+ });
+
connect(&undo, &QUndoStack::canUndoChanged, this, [=](bool b) {
m_toolBtneditors.value(ToolButtonIndex::UNDO_ACTION)->setEnabled(b);
});
@@ -223,10 +237,7 @@ void MainWindow::on_new_frompics() {
if (ensureSafeClose()) {
NewDialog d(NewType::FromPics, this);
if (d.exec()) {
- WingProgressDialog dw;
- dw.dialog()->setCancelButton(nullptr);
- dw.dialog()->setLabelText(tr("NewFromPicsGif"));
- dw.dialog()->setRange(0, 0);
+ WaitingLoop dw(tr("NewFromPicsGif"));
if (loadfromImages(d.getResult(), getNewFrameInterval())) {
_curfilename = QStringLiteral(":"); // 表示新建
setSaved(false);
@@ -235,7 +246,6 @@ void MainWindow::on_new_frompics() {
setEditModeEnabled(true);
} else {
}
- dw.pdialog()->close();
}
}
}
@@ -245,8 +255,7 @@ void MainWindow::on_new_fromgifs() {
if (ensureSafeClose()) {
NewDialog d(NewType::FromGifs, this);
if (d.exec()) {
- // WaitingDialog dw;
- // dw.start(tr("NewFromGifsGif"));
+ WaitingLoop dw(tr("NewFromGifsGif"));
if (loadfromGifs(d.getResult())) {
_curfilename = QStringLiteral(":"); // 表示新建
setSaved(false);
@@ -255,7 +264,6 @@ void MainWindow::on_new_fromgifs() {
setEditModeEnabled(true);
} else {
}
- // dw.close();
}
}
}
@@ -372,16 +380,8 @@ void MainWindow::on_export() {
void MainWindow::on_close() {
_player->stop();
if (ensureSafeClose()) {
-
- // editor->setBackgroudPix(QPixmap(":/images/icon.png"));
- // editor->fitPicEditor();
- // editor->scale(0.5, 0.5);
- // iSaved->setPixmap(infoSaveg);
- // iReadWrite->setPixmap(inforwg);
- // status->showMessage("");
-
+ _editor->setImage(QImage(NAMEICONRES(QStringLiteral("icon"))));
_model->clearData();
-
_curfilename.clear();
undo.clear();
setEditModeEnabled(false);
@@ -834,9 +834,16 @@ void MainWindow::on_fullscreen() { this->showFullScreen(); }
void MainWindow::on_about() { AboutSoftwareDialog().exec(); }
-void MainWindow::on_sponsor() {}
+void MainWindow::on_sponsor() {
+ QDesktopServices::openUrl(
+ QUrl(QStringLiteral("https://github.com/Wing-summer/"
+ "WingGifEditor2#%E6%8D%90%E5%8A%A9")));
+}
-void MainWindow::on_wiki() {}
+void MainWindow::on_wiki() {
+ QDesktopServices::openUrl(QUrl(
+ QStringLiteral("https://github.com/Wing-summer/WingGifEditor2/wiki")));
+}
RibbonTabContent *MainWindow::buildFilePage(RibbonTabContent *tab) {
auto shortcuts = QKeySequences::instance();
@@ -851,6 +858,7 @@ RibbonTabContent *MainWindow::buildFilePage(RibbonTabContent *tab) {
addPannelAction(pannel, QStringLiteral("open"), tr("Open"),
&MainWindow::on_open, QKeySequence::Open);
+
addPannelAction(pannel, QStringLiteral("recent"), tr("RecentFiles"),
EMPTY_FUNC, {}, m_recentMenu);
}
@@ -858,25 +866,26 @@ RibbonTabContent *MainWindow::buildFilePage(RibbonTabContent *tab) {
{
auto pannel = tab->addGroup(tr("Save"));
- auto a = addPannelAction(pannel, QStringLiteral("save"), tr("Save"),
- &MainWindow::on_save, QKeySequence::Save);
- m_editStateWidgets << a;
-
- a = addPannelAction(pannel, QStringLiteral("saveas"), tr("SaveAs"),
- &MainWindow::on_saveas,
- shortcuts.keySequence(QKeySequences::Key::SAVE_AS));
- m_editStateWidgets << a;
-
- a = addPannelAction(pannel, QStringLiteral("export"), tr("Export"),
- &MainWindow::on_export,
- shortcuts.keySequence(QKeySequences::Key::EXPORT));
- m_editStateWidgets << a;
- a = addPannelAction(
+ m_editStateWidgets << addPannelAction(pannel, QStringLiteral("save"),
+ tr("Save"), &MainWindow::on_save,
+ QKeySequence::Save);
+ m_editStateWidgets << addPannelAction(
+ pannel, QStringLiteral("saveas"), tr("SaveAs"),
+ &MainWindow::on_saveas,
+ shortcuts.keySequence(QKeySequences::Key::SAVE_AS));
+
+ m_editStateWidgets << addPannelAction(
+ pannel, QStringLiteral("export"), tr("Export"),
+ &MainWindow::on_export,
+ shortcuts.keySequence(QKeySequences::Key::EXPORT));
+ m_editStateWidgets << addPannelAction(
pannel, QStringLiteral("info"), tr("FileInfo"), [=] {
FileInfoDialog(_curfilename, _model->frameSize(), _comment)
.exec();
});
- m_editStateWidgets << a;
+ m_editStateWidgets << addPannelAction(pannel, QStringLiteral("close"),
+ tr("Close"),
+ &MainWindow::on_close);
}
return tab;
@@ -988,11 +997,10 @@ RibbonTabContent *MainWindow::buildViewPage(RibbonTabContent *tab) {
&MainWindow::on_last, QKeySequence(Qt::Key_Left));
_playDisWidgets << addPannelAction(pannel, QStringLiteral("gifplay"),
- tr("Play"), &MainWindow::on_play,
- QKeySequence(Qt::Key_F5));
- _btnPlayerStop =
- addPannelAction(pannel, QStringLiteral("pause"), tr("Stop"),
- &MainWindow::on_stop, QKeySequence(Qt::Key_F10));
+ tr("Play"), &MainWindow::on_play);
+ _btnPlayerStop = addPannelAction(pannel, QStringLiteral("pause"),
+ tr("Stop"), &MainWindow::on_stop);
+
_playDisWidgets << addPannelAction(
pannel, QStringLiteral("foreword"), tr("NextFrame"),
&MainWindow::on_next, QKeySequence(Qt::Key_Right));
@@ -1022,6 +1030,12 @@ RibbonTabContent *MainWindow::buildViewPage(RibbonTabContent *tab) {
[this] { _editor->setZoom(250); }));
menu->addAction(newAction(QStringLiteral("300%"),
[this] { _editor->setZoom(300); }));
+ menu->addSeparator();
+ auto a =
+ newAction(tr("FitInView"), [this] { _editor->fitInEditorView(); });
+ a->setIcon(ICONRES("fitinview"));
+ menu->addAction(a);
+
addPannelAction(pannel, QStringLiteral("scaleview"), tr("Scale"),
EMPTY_FUNC, {}, menu);
@@ -1096,19 +1110,27 @@ void MainWindow::openGif(const QString &filename) {
bool MainWindow::readGif(const QString &gif) {
GifReader reader;
+ connect(&reader, &GifReader::sigUpdateUIProcess, this,
+ [] { qApp->processEvents(); });
+
+ WaitingLoop dw(tr("ReadingGif"));
if (!reader.load(gif)) {
return false;
}
_comment = reader.comment();
_model->readGifReader(&reader);
_gallery->setCurrentIndex(_model->index(0));
+ _editor->fitOpenSize();
return true;
}
bool MainWindow::writeGif(const QString &gif, unsigned int loopCount,
const QString &comment) {
GifWriter writer(_model->width(), _model->height());
+ connect(&writer, &GifWriter::sigUpdateUIProcess, this,
+ [] { qApp->processEvents(); });
+ WaitingLoop dw(tr("WritingGif"));
writer.setExtString(comment);
writer.pushRange(_model->images(), _model->delays());
auto ret = writer.save(gif, loopCount);
@@ -1128,8 +1150,14 @@ bool MainWindow::exportGifFrames(const QString &dirPath, const char *ext) {
return false;
}
- for (int i = 0; i < _model->frameCount(); ++i) {
- _model->image(i).save(dir.absoluteFilePath(QString::number(i)), ext);
+ {
+ WaitingLoop dw(tr("ExportingGif"));
+
+#pragma omp parallel for
+ for (int i = 0; i < _model->frameCount(); ++i) {
+ _model->image(i).save(dir.absoluteFilePath(QString::number(i)),
+ ext);
+ }
}
return true;