diff --git a/CMakeLists.txt b/CMakeLists.txt index b275e55..c2c0664 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -64,7 +64,14 @@ include_directories( ${CMAKE_CURRENT_SOURCE_DIR} ) - +find_package(Threads REQUIRED) +find_package(PkgConfig REQUIRED) +pkg_check_modules(AIBASE kylin-ai-base) +include_directories(${AIBASE_INCLUDE_DIRS}) + +pkg_check_modules(Gsetting REQUIRED gsettings-qt) +include_directories(${Gsetting_INCLUDE_DIRS}) + ## Generate header with version number ecm_setup_version(${RELEASE_SERVICE_VERSION} @@ -308,6 +315,7 @@ set(kolourpaint_app_SRCS ${CMAKE_CURRENT_SOURCE_DIR}/widgets/kpTransparentColorCell.cpp ${CMAKE_CURRENT_SOURCE_DIR}/widgets/toolbars/kpColorToolBar.cpp ${CMAKE_CURRENT_SOURCE_DIR}/widgets/toolbars/kpToolToolBar.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/widgets/toolbars/kpAiDrawingBar.cpp ${CMAKE_CURRENT_SOURCE_DIR}/widgets/toolbars/options/kpToolWidgetBase.cpp ${CMAKE_CURRENT_SOURCE_DIR}/widgets/toolbars/options/kpToolWidgetBrush.cpp ${CMAKE_CURRENT_SOURCE_DIR}/widgets/toolbars/options/kpToolWidgetEraserSize.cpp @@ -345,7 +353,11 @@ target_link_libraries(kolourpaint KF${KF_MAJOR_VERSION}::KIOFileWidgets KF${KF_MAJOR_VERSION}::TextWidgets Qt${QT_MAJOR_VERSION}::PrintSupport + Threads::Threads ${KSANE_LIBRARIES} + ${AIBASE_LIBRARIES} + ${Gsetting_LIBRARIES} +# ${LIBUKUI_LOG4QT_PATH} kolourpaint_lgpl ) diff --git a/debian/changelog b/debian/changelog index 0b2cf56..f69cdfa 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1,3 +1,12 @@ +kolourpaint (4:23.08.3-ok3) nile; urgency=medium + + * BUG号 : 无 + * 需求号 : TASK AI画图 + * 其他改动说明 : 无 + * 其他改动影响域 : 无 + + -- shangxiaoyang Thu, 14 Mar 2024 20:43:16 +0800 + kolourpaint (4:23.08.3-ok2.0) nile; urgency=medium * BUG号 : 无 diff --git a/debian/control b/debian/control index fa8add2..02ec5eb 100644 --- a/debian/control +++ b/debian/control @@ -18,6 +18,8 @@ Build-Depends: cmake (>= 3.16.0~), libkf5xmlgui-dev (>= 5.90.0~), pkg-config, qtbase5-dev (>= 5.15.2~), + libkylin-ai-base-dev, + libgsettings-qt-dev, Standards-Version: 4.6.1 Rules-Requires-Root: no Homepage: https://apps.kde.org/en/kolourpaint @@ -27,7 +29,7 @@ Vcs-Git: https://gitee.com/openkylin/kolourpaint.git Package: kolourpaint Section: graphics Architecture: any -Depends: ${misc:Depends}, ${shlibs:Depends} +Depends: ${misc:Depends}, ${shlibs:Depends}, libkylin-ai-base0 Breaks: kolourpaint4 (<< 4:17.04) Replaces: kolourpaint4 (<< 4:17.04) Description: simple image editor and drawing application diff --git a/environments/tools/kpToolEnvironment.cpp b/environments/tools/kpToolEnvironment.cpp index f0346fc..8c96d6e 100644 --- a/environments/tools/kpToolEnvironment.cpp +++ b/environments/tools/kpToolEnvironment.cpp @@ -42,7 +42,7 @@ //-------------------------------------------------------------------------------- bool kpToolEnvironment::drawAntiAliased = true; - +bool kpToolEnvironment::AiDrawing = true; //-------------------------------------------------------------------------------- struct kpToolEnvironmentPrivate diff --git a/environments/tools/kpToolEnvironment.h b/environments/tools/kpToolEnvironment.h index 4bd6348..c982e58 100644 --- a/environments/tools/kpToolEnvironment.h +++ b/environments/tools/kpToolEnvironment.h @@ -152,6 +152,7 @@ public: void fitToPage () const; static bool drawAntiAliased; + static bool AiDrawing; private: diff --git a/kolourpaint.cpp b/kolourpaint.cpp index 0b85ee0..5cbe6fb 100644 --- a/kolourpaint.cpp +++ b/kolourpaint.cpp @@ -41,11 +41,15 @@ int main(int argc, char *argv []) { - QApplication app(argc, argv); -#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0) +#if QT_VERSION >= QT_VERSION_CHECK(5, 6, 0) QApplication::setAttribute(Qt::AA_UseHighDpiPixmaps); + QApplication::setAttribute(Qt::AA_EnableHighDpiScaling); +#endif +#if (QT_VERSION >= QT_VERSION_CHECK(5, 14, 0)) + QApplication::setHighDpiScaleFactorRoundingPolicy(Qt::HighDpiScaleFactorRoundingPolicy::PassThrough); #endif + QApplication app(argc, argv); KLocalizedString::setApplicationDomain("kolourpaint"); KAboutData aboutData diff --git a/kolourpaintui.rc b/kolourpaintui.rc index 0f3580c..e53640f 100644 --- a/kolourpaintui.rc +++ b/kolourpaintui.rc @@ -111,6 +111,7 @@ SYNC: Check for duplicate actions in menus caused by some of our actions + diff --git a/kpDefs.h b/kpDefs.h index db20dba..0358891 100644 --- a/kpDefs.h +++ b/kpDefs.h @@ -62,6 +62,7 @@ #define kpSettingShowGrid "Show Grid" #define kpSettingShowPath "Show Path" #define kpSettingDrawAntiAliased "Draw AntiAliased" +#define kpSettingAiDrawing "AI Drawing" #define kpSettingColorSimilarity "Color Similarity" #define kpSettingDitherOnOpen "Dither on Open if Screen is 15/16bpp and Image Num Colors More Than" #define kpSettingPrintImageCenteredOnPage "Print Image Centered On Page" diff --git a/mainWindow/kpMainWindow.cpp b/mainWindow/kpMainWindow.cpp index 645931b..50c35d4 100644 --- a/mainWindow/kpMainWindow.cpp +++ b/mainWindow/kpMainWindow.cpp @@ -109,6 +109,7 @@ void kpMainWindow::readGeneralSettings () d->configShowPath = cfg.readEntry (kpSettingShowPath, false); d->moreEffectsDialogLastEffect = cfg.readEntry (kpSettingMoreEffectsLastEffect, 0); kpToolEnvironment::drawAntiAliased = cfg.readEntry(kpSettingDrawAntiAliased, true); + kpToolEnvironment::AiDrawing = cfg.readEntry(kpSettingAiDrawing, true); if (cfg.hasKey (kpSettingOpenImagesInSameWindow)) { diff --git a/mainWindow/kpMainWindow.h b/mainWindow/kpMainWindow.h index 4261525..8c4858d 100644 --- a/mainWindow/kpMainWindow.h +++ b/mainWindow/kpMainWindow.h @@ -339,6 +339,9 @@ private slots: void slotScreenshot(); void slotMakeScreenshot(); + void slotAiDrawing(bool on); + void showAIImageData(const QPixmap &pixmaps); + void slotProperties (); bool save (bool localOnly = false); diff --git a/mainWindow/kpMainWindowPrivate.h b/mainWindow/kpMainWindowPrivate.h index 64fb604..1bcbd6a 100644 --- a/mainWindow/kpMainWindowPrivate.h +++ b/mainWindow/kpMainWindowPrivate.h @@ -58,6 +58,7 @@ class kpThumbnailView; class kpDocument; class kpViewManager; class kpColorToolBar; +class kpAIDrawingBar; class kpToolToolBar; class kpCommandHistory; class kpTool; @@ -264,6 +265,7 @@ struct kpMainWindowPrivate kpDocument *document; kpViewManager *viewManager; kpColorToolBar *colorToolBar; + kpAIDrawingBar *aiDrawToolBar; kpToolToolBar *toolToolBar; kpCommandHistory *commandHistory; diff --git a/mainWindow/kpMainWindow_Settings.cpp b/mainWindow/kpMainWindow_Settings.cpp index cba6483..a1dcc39 100644 --- a/mainWindow/kpMainWindow_Settings.cpp +++ b/mainWindow/kpMainWindow_Settings.cpp @@ -41,6 +41,7 @@ #include "kpDefs.h" #include "document/kpDocument.h" #include "widgets/toolbars/kpToolToolBar.h" +#include "widgets/toolbars/kpAiDrawingBar.h" #include "environments/tools/kpToolEnvironment.h" //--------------------------------------------------------------------- @@ -67,6 +68,21 @@ void kpMainWindow::setupSettingsMenuActions () connect (d->actionShowPath, &QAction::triggered, this, &kpMainWindow::slotShowPathToggled); slotEnableSettingsShowPath (); + d->aiDrawToolBar = new kpAIDrawingBar(this); + addDockWidget(Qt::RightDockWidgetArea, d->aiDrawToolBar); + addDockWidget(Qt::RightDockWidgetArea, d->aiDrawToolBar, Qt::Vertical); + connect(d->aiDrawToolBar, &kpAIDrawingBar::imageClicked, this, &kpMainWindow::showAIImageData); + if (kpToolEnvironment::AiDrawing) + d->aiDrawToolBar->show(); + else + d->aiDrawToolBar->hide(); + + auto actionAIDrawing = ac->add(QStringLiteral("file_aidrawing")); + actionAIDrawing->setText(i18n("Displays the AI authoring bar")); + actionAIDrawing->setChecked(kpToolEnvironment::AiDrawing); + connect (actionAIDrawing, &QAction::triggered, this, &kpMainWindow::slotAiDrawing); + + auto *action = ac->add(QStringLiteral("settings_draw_antialiased")); action->setText(i18n("Draw Anti-Aliased")); action->setChecked(kpToolEnvironment::drawAntiAliased); @@ -81,6 +97,35 @@ void kpMainWindow::setupSettingsMenuActions () //--------------------------------------------------------------------- +void kpMainWindow::slotAiDrawing(bool on) +{ + kpToolEnvironment::AiDrawing = on; + + KConfigGroup cfg(KSharedConfig::openConfig(), kpSettingsGroupGeneral); + + cfg.writeEntry(kpSettingAiDrawing, kpToolEnvironment::AiDrawing); + cfg.sync(); + + qDebug()<<"菜单栏是否选中:"<aiDrawToolBar->isHidden(); + if (on) + d->aiDrawToolBar->show(); + else + d->aiDrawToolBar->hide(); +} + + +void kpMainWindow::showAIImageData(const QPixmap &pixmaps) +{ + QPixmap pixmap = pixmaps; + auto *doc = new kpDocument(pixmap.width(), pixmap.height(), documentEnvironment()); + doc->setImage(pixmap.toImage()); + // Send document to current or new window. + setDocument(doc); + show(); + qDebug() << "slotAiDrawing 处理图像数据 :" << pixmaps; +} + + // private void kpMainWindow::enableSettingsMenuDocumentActions (bool /*enable*/) { diff --git a/pics/CMakeLists.txt b/pics/CMakeLists.txt index c56ef12..7f5c964 100644 --- a/pics/CMakeLists.txt +++ b/pics/CMakeLists.txt @@ -1,2 +1,4 @@ add_subdirectory( action ) add_subdirectory( app ) +add_subdirectory( custom ) +add_subdirectory( style ) diff --git a/pics/custom/AI-Drawing@2x.png b/pics/custom/AI-Drawing@2x.png new file mode 100644 index 0000000..f0e5e39 Binary files /dev/null and b/pics/custom/AI-Drawing@2x.png differ diff --git a/pics/custom/CMakeLists.txt b/pics/custom/CMakeLists.txt new file mode 100644 index 0000000..90c1d81 --- /dev/null +++ b/pics/custom/CMakeLists.txt @@ -0,0 +1,6 @@ +install(FILES + loading.gif + AI-Drawing@2x.png + slogo-Drawing.svg + bg@2x.png + DESTINATION ${DATA_INSTALL_DIR}/kolourpaint/pics) diff --git a/pics/custom/bg@2x.png b/pics/custom/bg@2x.png new file mode 100644 index 0000000..d519b5f Binary files /dev/null and b/pics/custom/bg@2x.png differ diff --git a/pics/custom/loading.gif b/pics/custom/loading.gif new file mode 100755 index 0000000..a9c4f06 Binary files /dev/null and b/pics/custom/loading.gif differ diff --git a/pics/custom/slogo-Drawing.svg b/pics/custom/slogo-Drawing.svg new file mode 100644 index 0000000..a1123f4 --- /dev/null +++ b/pics/custom/slogo-Drawing.svg @@ -0,0 +1,11 @@ + + + + + + + + + + + diff --git a/pics/style/CMakeLists.txt b/pics/style/CMakeLists.txt new file mode 100644 index 0000000..b8e3784 --- /dev/null +++ b/pics/style/CMakeLists.txt @@ -0,0 +1,36 @@ +install(FILES + style-all.png + style-anime.png + style-ancient.png + style-baroque.png + style-cartoon.png + style-conceptual.png + style-cyberpunk.png + style-futurism.png + style-lolita.png + style-low-poly.png + style-oil-painting.png + style-pixel.png + style-realistic.png + style-surrealism.png + style-ukiyoe.png + style-vaporwave.png + style-watercolour.png + style-all@2x.png + style-anime@2x.png + style-ancient@2x.png + style-baroque@2x.png + style-cartoon@2x.png + style-conceptual@2x.png + style-cyberpunk@2x.png + style-futurism@2x.png + style-lolita@2x.png + style-low-poly@2x.png + style-oil-painting@2x.png + style-pixel@2x.png + style-realistic@2x.png + style-surrealism@2x.png + style-ukiyoe@2x.png + style-vaporwave@2x.png + style-watercolour@2x.png + DESTINATION ${DATA_INSTALL_DIR}/kolourpaint/pics/style) diff --git a/pics/style/style-all.png b/pics/style/style-all.png new file mode 100644 index 0000000..c9fdebb Binary files /dev/null and b/pics/style/style-all.png differ diff --git a/pics/style/style-all@2x.png b/pics/style/style-all@2x.png new file mode 100644 index 0000000..2191bf2 Binary files /dev/null and b/pics/style/style-all@2x.png differ diff --git a/pics/style/style-ancient.png b/pics/style/style-ancient.png new file mode 100644 index 0000000..cde0bb3 Binary files /dev/null and b/pics/style/style-ancient.png differ diff --git a/pics/style/style-ancient@2x.png b/pics/style/style-ancient@2x.png new file mode 100644 index 0000000..e92173d Binary files /dev/null and b/pics/style/style-ancient@2x.png differ diff --git a/pics/style/style-anime.png b/pics/style/style-anime.png new file mode 100644 index 0000000..d4a611d Binary files /dev/null and b/pics/style/style-anime.png differ diff --git a/pics/style/style-anime@2x.png b/pics/style/style-anime@2x.png new file mode 100644 index 0000000..2cdf1f3 Binary files /dev/null and b/pics/style/style-anime@2x.png differ diff --git a/pics/style/style-baroque.png b/pics/style/style-baroque.png new file mode 100644 index 0000000..b9ec7fa Binary files /dev/null and b/pics/style/style-baroque.png differ diff --git a/pics/style/style-baroque@2x.png b/pics/style/style-baroque@2x.png new file mode 100644 index 0000000..4f53a36 Binary files /dev/null and b/pics/style/style-baroque@2x.png differ diff --git a/pics/style/style-cartoon.png b/pics/style/style-cartoon.png new file mode 100644 index 0000000..7bbac1e Binary files /dev/null and b/pics/style/style-cartoon.png differ diff --git a/pics/style/style-cartoon@2x.png b/pics/style/style-cartoon@2x.png new file mode 100644 index 0000000..71a2742 Binary files /dev/null and b/pics/style/style-cartoon@2x.png differ diff --git a/pics/style/style-conceptual.png b/pics/style/style-conceptual.png new file mode 100644 index 0000000..349b3b6 Binary files /dev/null and b/pics/style/style-conceptual.png differ diff --git a/pics/style/style-conceptual@2x.png b/pics/style/style-conceptual@2x.png new file mode 100644 index 0000000..bd90aa3 Binary files /dev/null and b/pics/style/style-conceptual@2x.png differ diff --git a/pics/style/style-cyberpunk.png b/pics/style/style-cyberpunk.png new file mode 100644 index 0000000..6491dc6 Binary files /dev/null and b/pics/style/style-cyberpunk.png differ diff --git a/pics/style/style-cyberpunk@2x.png b/pics/style/style-cyberpunk@2x.png new file mode 100644 index 0000000..e0a8484 Binary files /dev/null and b/pics/style/style-cyberpunk@2x.png differ diff --git a/pics/style/style-futurism.png b/pics/style/style-futurism.png new file mode 100644 index 0000000..ae0441c Binary files /dev/null and b/pics/style/style-futurism.png differ diff --git a/pics/style/style-futurism@2x.png b/pics/style/style-futurism@2x.png new file mode 100644 index 0000000..07ae54f Binary files /dev/null and b/pics/style/style-futurism@2x.png differ diff --git a/pics/style/style-lolita.png b/pics/style/style-lolita.png new file mode 100644 index 0000000..15ceda5 Binary files /dev/null and b/pics/style/style-lolita.png differ diff --git a/pics/style/style-lolita@2x.png b/pics/style/style-lolita@2x.png new file mode 100644 index 0000000..5b098d6 Binary files /dev/null and b/pics/style/style-lolita@2x.png differ diff --git a/pics/style/style-low-poly.png b/pics/style/style-low-poly.png new file mode 100644 index 0000000..ddd7358 Binary files /dev/null and b/pics/style/style-low-poly.png differ diff --git a/pics/style/style-low-poly@2x.png b/pics/style/style-low-poly@2x.png new file mode 100644 index 0000000..afb3901 Binary files /dev/null and b/pics/style/style-low-poly@2x.png differ diff --git a/pics/style/style-oil-painting.png b/pics/style/style-oil-painting.png new file mode 100644 index 0000000..cb1d14e Binary files /dev/null and b/pics/style/style-oil-painting.png differ diff --git a/pics/style/style-oil-painting@2x.png b/pics/style/style-oil-painting@2x.png new file mode 100644 index 0000000..f39b593 Binary files /dev/null and b/pics/style/style-oil-painting@2x.png differ diff --git a/pics/style/style-pixel.png b/pics/style/style-pixel.png new file mode 100644 index 0000000..af5f5f5 Binary files /dev/null and b/pics/style/style-pixel.png differ diff --git a/pics/style/style-pixel@2x.png b/pics/style/style-pixel@2x.png new file mode 100644 index 0000000..c698f30 Binary files /dev/null and b/pics/style/style-pixel@2x.png differ diff --git a/pics/style/style-realistic.png b/pics/style/style-realistic.png new file mode 100644 index 0000000..7859b15 Binary files /dev/null and b/pics/style/style-realistic.png differ diff --git a/pics/style/style-realistic@2x.png b/pics/style/style-realistic@2x.png new file mode 100644 index 0000000..52280bf Binary files /dev/null and b/pics/style/style-realistic@2x.png differ diff --git a/pics/style/style-surrealism.png b/pics/style/style-surrealism.png new file mode 100644 index 0000000..7d036c0 Binary files /dev/null and b/pics/style/style-surrealism.png differ diff --git a/pics/style/style-surrealism@2x.png b/pics/style/style-surrealism@2x.png new file mode 100644 index 0000000..6723bc9 Binary files /dev/null and b/pics/style/style-surrealism@2x.png differ diff --git a/pics/style/style-ukiyoe.png b/pics/style/style-ukiyoe.png new file mode 100644 index 0000000..6ff4735 Binary files /dev/null and b/pics/style/style-ukiyoe.png differ diff --git a/pics/style/style-ukiyoe@2x.png b/pics/style/style-ukiyoe@2x.png new file mode 100644 index 0000000..bb15cb3 Binary files /dev/null and b/pics/style/style-ukiyoe@2x.png differ diff --git a/pics/style/style-vaporwave.png b/pics/style/style-vaporwave.png new file mode 100644 index 0000000..aa106fb Binary files /dev/null and b/pics/style/style-vaporwave.png differ diff --git a/pics/style/style-vaporwave@2x.png b/pics/style/style-vaporwave@2x.png new file mode 100644 index 0000000..96de4d9 Binary files /dev/null and b/pics/style/style-vaporwave@2x.png differ diff --git a/pics/style/style-watercolour.png b/pics/style/style-watercolour.png new file mode 100644 index 0000000..a0465f4 Binary files /dev/null and b/pics/style/style-watercolour.png differ diff --git a/pics/style/style-watercolour@2x.png b/pics/style/style-watercolour@2x.png new file mode 100644 index 0000000..32d335b Binary files /dev/null and b/pics/style/style-watercolour@2x.png differ diff --git a/po/zh_CN/kolourpaint.po b/po/zh_CN/kolourpaint.po index 91bf703..154de81 100644 --- a/po/zh_CN/kolourpaint.po +++ b/po/zh_CN/kolourpaint.po @@ -1497,6 +1497,11 @@ msgstr "扫描图像..." msgid "Acquire Screenshot" msgstr "捕获屏幕截图" +#: mainWindow/kpMainWindow_File.cpp:122 +#, kde-format +msgid "Displays the AI authoring bar" +msgstr "显示AI创作栏" + #: mainWindow/kpMainWindow_File.cpp:122 #, kde-format msgid "Properties" @@ -2662,3 +2667,120 @@ msgstr "填充前景色" #, kde-format msgid "Opaque" msgstr "选区背景不透明" + +msgid "A cute cat pilot wearing goggles is soaring through the blue sky, cartoon style, HD" +msgstr "一只可爱的猫咪飞行员戴着护目镜,正在蓝天中翱翔,卡通风格,高清" + +msgid "Generate now" +msgstr "立即生成" + +msgid "Image description" +msgstr "图像描述" + +msgid "Image style" +msgstr "图像风格" + +msgid "Image ratio" +msgstr "图像比例" + +msgid "Scaling factor" +msgstr "缩放倍数" + +msgid "Generated quantity" +msgstr "生成数量" + +msgid "result" +msgstr "生成结果" + +msgid "more" +msgstr "更多" + +msgid "Pack up" +msgstr "收起" + +msgid "style-all" +msgstr "探索无限" + +msgid "style-ancient" +msgstr "古风" + +msgid "style-anime" +msgstr "二次元" + +msgid "style-realistic" +msgstr "写实风格" + +msgid "style-ukiyoe" +msgstr "浮世绘" + +msgid "style-low-poly" +msgstr "低多边形" + +msgid "style-futurism" +msgstr "未来主义" + +msgid "style-pixel" +msgstr "像素风格" + +msgid "style-conceptual" +msgstr "概念艺术" + +msgid "style-cyberpunk" +msgstr "赛博朋克" + +msgid "style-lolita" +msgstr "洛丽塔风" + +msgid "style-baroque" +msgstr "巴洛克风" + +msgid "style-surrealism" +msgstr "超现实主义" + +msgid "style-watercolour" +msgstr "水彩画" + +msgid "style-vaporwave" +msgstr "蒸汽波艺术" + +msgid "style-oil-painting" +msgstr "油画" + +msgid "style-cartoon" +msgstr "卡通画" + +msgid "Please configure the AI model account before you can use the mapping function." +msgstr "请先配置AI模型账号,方可使用麒思妙绘功能。" + +msgid "Configure now" +msgstr "立即配置" + +msgid "In formation..." +msgstr "生成中..." + +msgid "Network error" +msgstr "网络错误" + +msgid "Service error" +msgstr "服务错误" + +msgid "Authentication failure" +msgstr "鉴权失败" + +msgid "Request failed" +msgstr "请求失败" + +msgid "Task timeout" +msgstr "任务超时" + +msgid "Text length exceeds the limit" +msgstr "文本长度超限" + +msgid "Generation error" +msgstr "生成错误" + +msgid "Text or style errors" +msgstr "文本或风格错误" + +msgid "Parameter error" +msgstr "参数错误" diff --git a/widgets/toolbars/kpAiDrawingBar.cpp b/widgets/toolbars/kpAiDrawingBar.cpp new file mode 100644 index 0000000..37fe4f6 --- /dev/null +++ b/widgets/toolbars/kpAiDrawingBar.cpp @@ -0,0 +1,1206 @@ +/* + Copyright (c) 2003-2007 Clarence Dang + All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +#include "widgets/toolbars/kpAiDrawingBar.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include + +static int configVersion = 2; //AI作图基础版本和高级版本的分别 + +kpAIDrawingBar::kpAIDrawingBar(QWidget *parent) + : QDockWidget (parent) +{ + setTitleBarWidget(new QWidget()); + setFeatures(QDockWidget::DockWidgetMovable | QDockWidget::DockWidgetFloatable); + setAcceptDrops (false); + + if(!getConfigStatus()) + loginConfigurationPage(); + else + initUI(); + + setFixedWidth(250); +} + +kpAIDrawingBar::~kpAIDrawingBar() +{ + if (AiSettings) + delete AiSettings; +} + +/** + * @brief kpAIDrawingBar::getConfigStatus + * 获取AI画图秘钥是否配置 + * @return 是否配置 + */ +bool kpAIDrawingBar::getConfigStatus() +{ + bool res = false; + if (QGSettings::isSchemaInstalled(AI_GSETTINGS)){ + AiSettings = new QGSettings(AI_GSETTINGS); + connect(AiSettings, &QGSettings::changed, this, &kpAIDrawingBar::onConfigSettingsChange); + res = AiSettings->get(AI_KEY).toBool(); + } + + return res; +} + +/** + * @brief kpAIDrawingBar::onConfigSettingsChange + * 配置反馈回调函数 + * @param key + */ +void kpAIDrawingBar::onConfigSettingsChange(const QString &key) +{ + qDebug()<<"key == "<get("isVisionSetup").toBool()){ + if (configWidget) { + delete configWidget; + initUI(); + } + } + } +} + +/** + * @brief kpAIDrawingBar::loginConfigurationPage + * 登录配置界面函数 + */ +void kpAIDrawingBar::loginConfigurationPage() +{ + configWidget = new QWidget(this); + QVBoxLayout* layout = new QVBoxLayout(configWidget); + + QLabel* label_logo = new QLabel(this); + label_logo->setPixmap(QPixmap(DRAWING_IMAGE)); + label_logo->setScaledContents(true); + label_logo->setFixedSize(54,52); + + QLabel* label_slogo = new QLabel(this); + label_slogo->setPixmap(QPixmap(SLOGO_IMAGE)); + label_slogo->setScaledContents(true); + label_slogo->setFixedSize(168,24); + + QLabel* label_config = new QLabel(this); + label_config->setText(i18n("Please configure the AI model account before you can use the mapping function.")); + label_config->setFixedSize(218,52); + label_config->setAlignment(Qt::AlignCenter); + label_config->setWordWrap(true); + label_config->setStyleSheet("color: #B8B8B8;"); + + QPushButton* button_config = new QPushButton(i18n("Configure now"),this); + button_config->setFixedSize(112,36); + button_config->setStyleSheet("QPushButton" + "{ background-color: #3790FA; " + "color: white; " + "border: none;" + "border-radius: 5px; }"); + + QLabel* label_bg = new QLabel(this); + label_bg->setFixedSize(250, 160); + label_bg->setPixmap(QPixmap(BG_IMAGE)); + label_bg->setScaledContents(true); + + layout->addStretch(25); + layout->addWidget(label_logo, 0, Qt::AlignCenter); + layout->addStretch(1); + layout->addWidget(label_slogo, 1, Qt::AlignCenter); + layout->addStretch(1); + layout->addWidget(label_config, 2, Qt::AlignCenter); + layout->addStretch(1); + layout->addSpacing(15); + layout->addWidget(button_config, 3, Qt::AlignCenter); + layout->addStretch(25); + layout->addWidget(label_bg, 4); + + connect(button_config, &QPushButton::clicked, this, &kpAIDrawingBar::onConfigButtonClicked); + configWidget->setLayout(layout); + setWidget(configWidget); + +} + +/** + * @brief kpAIDrawingBar::onConfigButtonClicked + * 登录配置按钮回调函数,调用秘钥配置界面 + */ +void kpAIDrawingBar::onConfigButtonClicked() +{ + QDBusInterface *m_dbusInterface = new QDBusInterface(KYLIN_AI_DBUS, + KYLIN_AI_PATH, + KYLIN_AI_DBUS, + QDBusConnection::sessionBus(), + this); + if(m_dbusInterface->isValid()){ + m_dbusInterface->call("setModel"); + } + delete m_dbusInterface; +} + + +/** + * @brief kpAIDrawingBar::getconfigVersionData + * 获取AI作图调用的模型是基础版本还是高级版本 + */ +void kpAIDrawingBar::getconfigVersionData() +{ + QString jsonFilePath = QDir::homePath() + "/.config/model_manager.json"; + + qDebug()<setWidgetResizable(true); + auto *centralWidget = new QWidget(scrollArea); + + textBox = QString("A cute cat pilot wearing goggles is soaring through the blue sky, cartoon style, HD"); + + colorfulButtonStyle = "QPushButton " + "{ background: qlineargradient(" + "x1: 0, y1: 0, x2: 1, y2: 0," + "stop: 0 #3790FA, " + "stop: 1 #E85CFF);" + "color: white; " + "border: none;" + "border-radius: 5px; }"; + + colorGrayButtonStyle = "QPushButton" + "{ background-color: #E6E6E6; " + "color: #2626268C; " + "border: none;" + "border-radius: 5px; }"; + // 获取基础版本/高级版本 + getconfigVersionData(); + + if (configVersion == 2) + AIImageSize = QSize(640,360); + else if (configVersion == 1) + AIImageSize = QSize(1536, 1024); + + /* 图像描述布局 */ + auto *label = new QLabel(i18n("Image description")); + label->setAlignment(Qt::AlignLeft | Qt::AlignTop); + label->setFixedSize(224,30); + + QTextEdit *inputBox = new QTextEdit(); + inputBox->setPlaceholderText(i18n(textBox.toLocal8Bit().data())); + inputBox->setWordWrapMode(QTextOption::WrapAtWordBoundaryOrAnywhere); + inputBox->setFixedSize(224,136); + + /* 图像风格布局 */ + auto *styleLabel = new QLabel(i18n("Image style")); + styleLabel->setAlignment(Qt::AlignLeft | Qt::AlignTop); + styleLabel->setFixedSize(180, 30); + + styleGrid = new QGridLayout(); + addStyleWidget(); + + /* 图像比例布局 */ + ratioButtonGroup = new QButtonGroup(this); + auto *ratioLabel = new QLabel(i18n("Image ratio")); + ratioLabel->setAlignment(Qt::AlignLeft | Qt::AlignTop); + ratioLabel->setFixedSize(180, 30); + + QGridLayout *ratioGrid = new QGridLayout(); + if (configVersion == 2) { + addRatioButtons(ratioGrid, "16:9", 0); + addRatioButtons(ratioGrid, "1:1", 1); + addRatioButtons(ratioGrid, "9:16", 2); + } + else if (configVersion == 1) { + addRatioButtons(ratioGrid, "3:2", 0); + addRatioButtons(ratioGrid, "1:1", 1); + addRatioButtons(ratioGrid, "2:3", 2); + } + + /* 缩放倍数布局 */ + QLabel *multipleLabel; + QGridLayout *multipleLayout; + if (configVersion == 2) { + multipleButtonGroup = new QButtonGroup(this); + multipleLabel = new QLabel(i18n("Scaling factor")); + multipleLabel->setAlignment(Qt::AlignLeft | Qt::AlignTop); + multipleLabel->setFixedSize(180, 30); + + multipleLayout = new QGridLayout(); + addMultipleButton(multipleLayout, "1x", 0); + addMultipleButton(multipleLayout, "2x", 1); + addMultipleButton(multipleLayout, "4x", 2); + } + /* 生成数量布局 */ + quantityButtonGroup = new QButtonGroup(this); + QLabel *quantityLabel = new QLabel(i18n("Generated quantity")); + quantityLabel->setAlignment(Qt::AlignLeft | Qt::AlignTop); + quantityLabel->setFixedSize(180, 30); + + QGridLayout *quantityLayout = new QGridLayout(); + addQuantityButtons(quantityLayout); + + /* 立即生成按钮 */ + buildButton = new QPushButton(i18n("Generate now"), this); + buildButton->setFixedSize(224,36); + buildButton->setStyleSheet(colorGrayButtonStyle); + buildButton->setEnabled(false); + buildButtonFlag = false; + + /* 分页功能 */ + stackedWidget = new QStackedWidget(centralWidget); + + /* 生成结果布局 */ + resultGrid = new QHBoxLayout(this); + resultLabel = new QLabel(i18n("result")); + QPushButton *previousButton = new QPushButton(this); + pageLabel = new QLabel(tr("1")); + QPushButton *nextButton = new QPushButton(this); + resultLabel->setFixedSize(80,30); + previousButton->setIcon(QIcon::fromTheme("go-previous-symbolic")); + previousButton->setFixedSize(30,30); + previousButton->setStyleSheet("QPushButton { background-color: transparent; }"); + pageLabel->setFixedSize(50,30); + pageLabel->setAlignment(Qt::AlignCenter); + nextButton->setFixedSize(30,30); + nextButton->setIcon(QIcon::fromTheme("go-previous-symbolic-rtl")); + nextButton->setStyleSheet("QPushButton { background-color: transparent; }"); + + resultGrid->addWidget(resultLabel); + resultGrid->addStretch(); + resultGrid->addWidget(previousButton); + resultGrid->addWidget(pageLabel); + resultGrid->addWidget(nextButton); + resultGrid->setAlignment(pageLabel, Qt::AlignRight); + + /* 设置整体布局 */ + vbox = new QBoxLayout(QBoxLayout::TopToBottom, centralWidget); + vbox->setMargin (2); + vbox->setSpacing (5); + vbox->setAlignment(Qt::AlignTop); + + vbox->addWidget(label); + vbox->addWidget(inputBox); + vbox->addSpacing(15); + vbox->addWidget(styleLabel); + vbox->addLayout(styleGrid); + vbox->addSpacing(15); + vbox->addWidget(ratioLabel); + vbox->addLayout(ratioGrid); + if (configVersion == 2) { + vbox->addSpacing(15); + vbox->addWidget(multipleLabel); + vbox->addLayout(multipleLayout); + } + vbox->addSpacing(15); + vbox->addWidget(quantityLabel); + vbox->addLayout(quantityLayout); + vbox->addSpacing(15); + vbox->addWidget(buildButton); + vbox->addSpacing(15); + vbox->addLayout(resultGrid); + vbox->addWidget(stackedWidget); + + vbox->setContentsMargins(5,5,15,5); + // 隐藏resultGrid中的所有子控件 + for (int i = 0; i < resultGrid->count(); ++i) + { + QLayoutItem *item = resultGrid->itemAt(i); + if (item && item->widget()) + item->widget()->setVisible(false); + } + + connect(buildButton, &QPushButton::clicked, this, &kpAIDrawingBar::onGenerateButtonClicked); + connect(inputBox,&QTextEdit::textChanged, this, &kpAIDrawingBar::handleInputTextChanged); + connect(previousButton, &QPushButton::clicked, this, &kpAIDrawingBar::showPreviousPage); + connect(nextButton, &QPushButton::clicked, this, &kpAIDrawingBar::showNextPage); + connect(&aiThread, &AIModeDataThread::finishedSignal, this, &kpAIDrawingBar::onThreadFinished); + + scrollArea->setWidget(centralWidget); + scrollArea->setVerticalScrollBarPolicy(Qt::ScrollBarAsNeeded); + scrollArea->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff); + + setWidget(scrollArea); +} + +/** + * @brief kpAIDrawingBar::addStyleGrid + * 添加风格布局 + * @param widget + * @param line + */ +void kpAIDrawingBar::addStyleGrid(QWidget *widget, int line) +{ + styleGrid->addWidget(widget, line / 3, line % 3); +} + +/** + * @brief kpAIDrawingBar::addStyleWidget + * 添加风格窗口 + */ +void kpAIDrawingBar::addStyleWidget() +{ + QString path = "/usr/share/kolourpaint/pics/style/%1"; + QStringList styleList = {"style-ancient", "style-anime", + "style-realistic","style-ukiyoe"}; + + QStringList styleMoreList ={ "style-futurism", "style-pixel", "style-conceptual", "style-cyberpunk", + "style-lolita", "style-baroque", "style-surrealism", "style-watercolour", + "style-vaporwave", "style-oil-painting","style-cartoon"}; + + + + moreButton = new QPushButton(); + moreButton->setText(i18n("more")); + moreButton->setFixedSize(72, 40); + moreButton->setFont(QFont("Arial", 8)); + moreButton->setProperty("useButtonPalette", true); + + QWidget *widget_all = addAllStyleLabel(path.arg("style-all@2x.png"), "style-all", 0); + widget_low_poly = addStyleLabel(path.arg("style-low-poly@2x.png"), "style-low-poly", 5); + + styleGrid->addWidget(widget_all, 0, 0, Qt::AlignTop); + for (int i = 0; i < styleList.size(); ++i) + { + QString iconPath = path.arg(styleList[i]) + "@2x.png"; + QString labelText = styleList[i]; + QWidget *widget = addStyleLabel(iconPath, labelText, i+1); + addStyleGrid(widget, i+1); + } + styleGrid->addWidget(moreButton, 1, 2,Qt::AlignTop); + for (int i = 0; i < styleMoreList.size(); ++i) + { + QString iconPath = path.arg(styleMoreList[i]) + "@2x.png"; + QString labelText = styleMoreList[i]; + QWidget *widget = addStyleLabel(iconPath, labelText, i + 6); + addStyleGrid(widget, i + 6); + } + + for (int i = 6; i < styleGrid->count(); ++i) + { + styleGrid->itemAt(i)->widget()->setVisible(false); + } + + styleFlag = true; + + connect(moreButton,&QPushButton::clicked, this, &kpAIDrawingBar::onStyleMoreButtonClick); + +} + +/** + * @brief kpAIDrawingBar::onStyleMoreButtonClick + * 风格点击回调事件 + */ +void kpAIDrawingBar::onStyleMoreButtonClick() +{ + if (styleFlag) { + for (int i = 0; i < styleGrid->count(); ++i) + { + styleGrid->itemAt(i)->widget()->setVisible(styleFlag); + } + + moreButton->setText(i18n("Pack up")); + + styleGrid->removeWidget(moreButton); + + addStyleGrid(widget_low_poly, 5); + styleGrid->addWidget(moreButton, 5, 2,Qt::AlignTop); + } else { + for (int i = 5; i < styleGrid->count()-1; ++i) + { + styleGrid->itemAt(i)->widget()->setVisible(styleFlag); + } + + moreButton->setText(i18n("more")); + + styleGrid->removeWidget(moreButton); + styleGrid->removeWidget(widget_low_poly); + + addStyleGrid(widget_low_poly, 17); + styleGrid->addWidget(moreButton, 1, 2, Qt::AlignTop); + } + + styleFlag = !styleFlag; +} + +/** + * @brief kpAIDrawingBar::addAllStyleLabel + * 添加探索无限风格函数 + * @param iconPath + * @param labelText + * @param line + * @return + */ +QWidget *kpAIDrawingBar::addAllStyleLabel(QString iconPath, QString labelText, int line) +{ + QWidget *widget = new QWidget(); + QVBoxLayout *styleVBox = new QVBoxLayout(widget); + + QLabel *iconLabel = new QLabel(this); + iconLabel->setObjectName("iconLabel"); + iconLabel->setFixedSize(72,42); + iconLabel->setPixmap(QPixmap(iconPath).scaled(112,64, Qt::KeepAspectRatio,Qt::SmoothTransformation)); + iconLabel->setScaledContents(true); + iconLabel->setAlignment(Qt::AlignCenter); + + QLabel *textLabel = new QLabel(i18n(labelText.toLocal8Bit().data()), this); + textLabel->setObjectName("textLabel"); + textLabel->setFixedSize(72,16); + textLabel->setFont(QFont("Arial", 8)); + textLabel->setAlignment(Qt::AlignCenter); + textLabel->setProperty("labelStyle", line); + + iconLabel->setStyleSheet("border: 2px solid #3790FA; border-radius: 5px;"); + textLabel->setStyleSheet("color: #3790FA;"); + selectedIconLabel = iconLabel; + selectedTextLabel = textLabel; + + styleVBox->setMargin (0); + styleVBox->setSpacing (2); + styleVBox->addWidget(iconLabel); + styleVBox->addWidget(textLabel); + + widget->setFixedSize(72,58); + + widget->installEventFilter(this); + + return widget; +} + +/** + * @brief kpAIDrawingBar::addStyleLabel + * 添加风格布局函数 + * @param iconPath + * @param labelText + * @param line + * @return + */ +QWidget *kpAIDrawingBar::addStyleLabel(QString iconPath, QString labelText, int line) +{ + QWidget *widget = new QWidget(); + QVBoxLayout *styleVBox = new QVBoxLayout(widget); + + QLabel *iconLabel = new QLabel(this); + iconLabel->setObjectName("iconLabel"); + iconLabel->setFixedSize(72,42); + iconLabel->setPixmap(QPixmap(iconPath).scaled(112,64, Qt::KeepAspectRatio,Qt::SmoothTransformation)); + iconLabel->setScaledContents(true); + iconLabel->setAlignment(Qt::AlignCenter); + + QLabel *textLabel = new QLabel(i18n(labelText.toLocal8Bit().data()), this); + textLabel->setObjectName("textLabel"); + textLabel->setFixedSize(72,16); + textLabel->setFont(QFont("Arial", 8)); + textLabel->setAlignment(Qt::AlignCenter); + textLabel->setProperty("labelStyle", line); + + styleVBox->setMargin (0); + styleVBox->setSpacing (2); + styleVBox->addWidget(iconLabel); + styleVBox->addWidget(textLabel); + widget->setFixedSize(72,58); + + widget->installEventFilter(this); + + return widget; +} + +/** + * @brief kpAIDrawingBar::eventFilter + * 事件重载回调函数 + * @param obj + * @param event + * @return + */ +bool kpAIDrawingBar::eventFilter(QObject *obj, QEvent *event) +{ + if (event->type() == QEvent::MouseButtonPress) + { + handleLabelClicked(obj); + return true; + } + return QObject::eventFilter(obj, event); +} + +/** + * @brief kpAIDrawingBar::handleLabelClicked + * 新增的槽函数,处理风格部分的点击事件 + * @param clickedObject + */ +void kpAIDrawingBar::handleLabelClicked(QObject *clickedObject) +{ + QWidget *clickedWidget = qobject_cast(clickedObject); + + if (!clickedWidget){ + qDebug()<<"clickedWidget is null"; + return; + } + + QLabel *iconLabel = clickedWidget->findChild("iconLabel"); + QLabel *textLabel = clickedWidget->findChild("textLabel"); + + if (!iconLabel || !textLabel){ + qDebug()<<"clickedLable is null"; + return; + } + + if(!selectedIconLabel || !selectedTextLabel){ + qDebug()<<"selectedIconLabel/selectedTextLabel is null"; + return; + } + + if (selectedIconLabel != iconLabel) { + selectedIconLabel->setStyleSheet(""); + selectedTextLabel->setStyleSheet(""); + selectedIconLabel = nullptr; + selectedTextLabel = nullptr; + } + iconLabel->setStyleSheet("border: 2px solid #3790FA; border-radius: 5px;"); + textLabel->setStyleSheet("color: #3790FA;"); + selectedIconLabel = iconLabel; + selectedTextLabel = textLabel; + int identifier = textLabel->property("labelStyle").toInt(); + ImageStyle = (VisionImageStyle)identifier; +} + +/** + * @brief kpAIDrawingBar::addRatioButtons + * 添加比例按钮 + * @param layout + * @param name + * @param line + */ +void kpAIDrawingBar::addRatioButtons(QGridLayout *layout, QString name, int line) +{ + // 添加比例按钮 + QPushButton *ratioButton = new QPushButton(this); + ratioButton->setText(name); + ratioButton->setFixedSize(69,24); + ratioButton->setCheckable(true); + ratioButton->setAutoDefault(false); + if (line == 0) + ratioButton->click(); + ratioButtonGroup->addButton(ratioButton, line); + connect(ratioButton, &QPushButton::clicked, [this, line]() { + if (line == 0) { + AIImageSize = QSize(640, 360); + if (configVersion == 1) + AIImageSize = QSize(1536, 1024); + } + else if (line == 1){ + AIImageSize = QSize(512, 512); + if (configVersion == 1) + AIImageSize = QSize(1024, 1024); + } + else if (line == 2){ + AIImageSize = QSize(360, 640); + if (configVersion == 1) + AIImageSize = QSize(1024, 1536); + } + else{ + AIImageSize = QSize(640, 360); + if (configVersion == 1) + AIImageSize = QSize(1536, 1024); + } + + ratioNum = line; + qDebug()<<"处理比例按钮点击事件: AIImageSize = "<< AIImageSize; + }); + layout->addWidget(ratioButton, line / 3, line % 3); +} + +/** + * @brief kpAIDrawingBar::addMultipleButton + * 添加倍数按钮 + * @param layout + * @param name + * @param line + */ +void kpAIDrawingBar::addMultipleButton(QGridLayout *layout, QString name, int line) +{ + QPushButton *multipleButton = new QPushButton(this); + multipleButton->setText(name); + multipleButton->setFixedSize(69, 24); + multipleButton->setCheckable(true); + multipleButton->setAutoDefault(false); + if (line == 0) + multipleButton->click(); + multipleButtonGroup->addButton(multipleButton, line); + connect(multipleButton, &QPushButton::clicked, [this, line]() { + if (line == 0) + multipleNum = 1; + else if (line == 1) + multipleNum = 2; + else if (line == 2) + multipleNum = 4; + else + multipleNum = 1; + + qDebug()<<"处理倍数按钮点击事件: line = "<< multipleNum; + }); + layout->addWidget(multipleButton, line / 3, line % 3); +} + +/** + * @brief kpAIDrawingBar::addQuantityButtons + * 添加数量按钮 + * @param layout + */ +void kpAIDrawingBar::addQuantityButtons(QGridLayout *layout) +{ + for (int i = 0; i < 4; ++i) + { + QString buttonName = QString::number(1 << i); + if (i == 3 && configVersion == 1){ + buttonName = QString::number(6); + } + QPushButton *quantityButton = new QPushButton(buttonName); + quantityButton->setFixedSize(50,24); + quantityButton->setCheckable(true); + + if (i == 2) + quantityButton->click(); + quantityButtonGroup->addButton(quantityButton, i); + connect(quantityButton, &QPushButton::clicked, [this, i](){ + if(i == 0) { + quantityNum = 1; + } + else if (i == 1) { + quantityNum = 2; + } + else if (i == 2){ + quantityNum = 4; + } + else if (i == 3 && configVersion == 2){ + quantityNum = 8; + } + else if (i == 3 && configVersion == 1){ + quantityNum = 6; + } + else { + quantityNum = 4; + } + qDebug()<<"处理数量按钮点击事件 line = "<addWidget(quantityButton, i / 4, i % 4); + } +} + +/** + * @brief kpAIDrawingBar::onGenerateButtonClicked + * 立即生成按钮回调函数 + */ +void kpAIDrawingBar::onGenerateButtonClicked() +{ + QString resultText = static_cast(findChild())->toPlainText(); + if(!resultText.isEmpty()) + textBox = resultText; + + qDebug() << "输入文字为:" << textBox; + + buildButton->setEnabled(false); + buildButton->setText(i18n("In formation...")); + buildButton->setStyleSheet(colorGrayButtonStyle); + buildButtonFlag = true; + + // 显示resultGrid中的所有子控件 + for (int i = 0; i < resultGrid->count(); ++i) + { + QLayoutItem *item = resultGrid->itemAt(i); + if (item && item->widget()) + item->widget()->setVisible(true); + } + // 更新图像 + updateImageGrid(); +} + +/** + * @brief kpAIDrawingBar::handleInputTextChanged + * 文字输入回调函数 + */ +void kpAIDrawingBar::handleInputTextChanged() +{ + //考虑添加生成中判断 + QString userText = static_cast(findChild())->toPlainText().trimmed(); + bool enableButton = !userText.isEmpty(); + if (enableButton && !buildButton->isEnabled() && !buildButtonFlag) { + qDebug()<<"buildButton set true"; + buildButton->setEnabled(enableButton); + buildButton->setStyleSheet(colorfulButtonStyle); + } + else if (!enableButton && buildButton->isEnabled()) { + buildButton->setEnabled(enableButton); + buildButton->setStyleSheet(colorGrayButtonStyle); + } +} + +/** + * @brief AIModeDataThread::generateImageCallback + * AI生成后回调函数 + * @param imageData + * @param userData + */ +void AIModeDataThread::generateImageCallback(VisionImageData imageData, void* userData){ + + qDebug()<<"AI生成回调函数: length:"<finishedSignal(false, map, imageData.index, imageData.total, imageData.error_code); + emit AIMode->finishedSignal(true, map, imageData.index, imageData.total, imageData.error_code); +} + +/** + * @brief kpAIDrawingBar::addPageAndStoreImages + * 添加AI生成后的图片及页 + */ +void kpAIDrawingBar::addPageAndStoreImages() +{ + // Create a new page + QWidget *newPage = new QWidget(); + + // Get the current set of images + QVector currentImages = imagesVector.last(); + + QGridLayout *pageLayout = new QGridLayout(newPage); + pageLayout->setMargin (2); + pageLayout->setSpacing (5); + pageLayout->setAlignment(Qt::AlignTop | Qt::AlignCenter); + + for (int i = 0; i < currentImages.size(); ++i) { + QPixmap pixmap = currentImages[i]; + setAiPixmap(pixmap, i, pageLayout); + } + stackedWidget->addWidget(newPage); + stackedWidget->setCurrentIndex(stackedWidget->count() - 1); + updatePageLabel(); +} + +/** + * @brief kpAIDrawingBar::createPixmapWithText + * 生成图片报错处理 + * @param text + * @return + */ +QPixmap kpAIDrawingBar::createPixmapWithText(const QString &text) +{ + QSize size; + if (configVersion == 2) + size = AIImageSize/4; + else if (configVersion == 1) + size = AIImageSize/8; + else + size = AIImageSize/4; + + QPixmap pixmap(size); + pixmap.fill(QColor("#E6E6E6")); + + QColor color("#B8B8B8"); + QPainter painter(&pixmap); + + QFontMetrics metrics(painter.font()); + QString wrappedText = metrics.elidedText(i18n(text.toLocal8Bit().data()), Qt::ElideRight, pixmap.rect().width()); + + painter.setPen(color); + painter.drawText(pixmap.rect(), Qt::AlignCenter, wrappedText); + painter.end(); + + qDebug()<<"Error message:"<()); + } + if (errorCode != 0) + map = AIGeneratesErrorHandling(errorCode); + else + map = pixmap; + + if (imagesVector.size() > 0 ){ + imagesVector.last().append(map); + } + if (imageIndex + 1 == imageSum){ + buildButton->setEnabled(true); + buildButton->setText(i18n("Generate now")); + buildButton->setStyleSheet(colorfulButtonStyle);//设置立即生成按钮为立即生成 + buildButtonFlag = false; + addPageAndStoreImages(); + } + aiThread.exit(); +} + +/** + * @brief AIModeDataThread::someFunctionInThread + * AI服务调用函数 + * @return + */ +bool AIModeDataThread::someFunctionInThread() +{ + VisionSession session = nullptr; + VisionResult ret = vision_create_session(&session); + + if (ret != VISION_SUCCESS) { + qDebug()<<"VisionResult 创建失败 VisionResult = "<count())); +} + +/** + * @brief kpAIDrawingBar::showPreviousPage + * 上一页回调函数 + */ +void kpAIDrawingBar::showPreviousPage() +{ + if (stackedWidget->count() > 1 && currentPageIndx > 0) { + currentPageIndx--; + stackedWidget->setCurrentIndex(currentPageIndx); + updatePageLabel(); + } + else if (stackedWidget->count() > 1 && currentPageIndx == 0) { + currentPageIndx = stackedWidget->count() - 1; + stackedWidget->setCurrentIndex(currentPageIndx); + updatePageLabel(); + } + qDebug()<<"stackedWidget->count() = "<count()<<"currentPageIndx="<count() > 1 && currentPageIndx < stackedWidget->count() - 1) { + currentPageIndx++; + stackedWidget->setCurrentIndex(currentPageIndx); + updatePageLabel(); + } + else if (stackedWidget->count() > 1 && currentPageIndx == stackedWidget->count() - 1) { + currentPageIndx = 0; + stackedWidget->setCurrentIndex(currentPageIndx); + updatePageLabel(); + } + qDebug()<<"stackedWidget->count() = "<count()<<"currentPageIndx="<setMargin (2); + pageLayout->setSpacing (5); + pageLayout->setAlignment(Qt::AlignTop | Qt::AlignCenter); + + for(int i = 0; i < quantityNum; i++){ + QLabel *label = new QLabel(); + movie = new QMovie(LOADING_IMAGE); + if (quantityNum == 1) + movie->setScaledSize(QSize(50,50)); + else + movie->setScaledSize(QSize(30,30)); + label->setMovie(movie); + movie->start(); + label->setStyleSheet("QLabel {" + "background-color: #E6E6E6;" + "border-radius: 5px;}"); + + label->setFixedSize(labelSize); + label->setAlignment(Qt::AlignCenter); + pageLayout->addWidget(label, i / imageColumn, i % imageColumn, Qt::AlignTop); + } + + stackedWidget->addWidget(newWidget); + stackedWidget->setCurrentIndex(stackedWidget->count() - 1); + + qDebug()<<"updateImageGrid : currentPageIndx = "<count(); + updatePageLabel(); + + qDebug()< + All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + + +#ifndef KP_AI_DRAWINGBAR_H +#define KP_AI_DRAWINGBAR_H + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#define LOADING_IMAGE "/usr/share/kolourpaint/pics/loading.gif" +#define BG_IMAGE "/usr/share/kolourpaint/pics/bg@2x.png" +#define SLOGO_IMAGE "/usr/share/kolourpaint/pics/slogo-Drawing.svg" +#define DRAWING_IMAGE "/usr/share/kolourpaint/pics/AI-Drawing@2x.png" +#define KYLIN_AI_DBUS "com.kylin.aiassistant" +#define KYLIN_AI_PATH "/com/kylin/aiassistant" +#define AI_GSETTINGS "org.kylin.aiassistant.settings" +#define AI_KEY "isVisionSetup" + + +/** + * @brief The AIModeDataThread class + * 线程类,用于跑AI的服务 + */ +class AIModeDataThread : public QThread { + Q_OBJECT + +public: + void run() override { + someFunctionInThread(); + } + void setAIData (QString str, QSize size, int multiple, int quantity, VisionImageStyle Style){ + textBox = str; + AIImageSize = size; + multipleNum = multiple; + quantityNum = quantity; + ImageStyle = Style; + } + +signals: + void finishedSignal(bool flag, QPixmap pixmap, int imageIndex, int imageSum, int errorCode); + +private: + bool someFunctionInThread(); + void sendErrorSignal(int ret){ + emit finishedSignal(false, QPixmap(), 0, 1, ret); + for(int i = 0; i < quantityNum; i++) + emit finishedSignal(true, QPixmap(), i, quantityNum, ret); + } + static void generateImageCallback(VisionImageData imageData, void* userData); + +private: + QPixmap pixmap; + int quantityNum = 4; //数量按钮 + int multipleNum = 1; //倍数按钮 + QSize AIImageSize; + QString textBox; + VisionImageStyle ImageStyle; +}; + +/** + * @brief The imageClickableLabel class + * QLabel点击事件类,用于对图片做处理传输 + */ +class imageClickableLabel : public QLabel +{ + Q_OBJECT + +signals: + void labelClicked(const QPixmap &pixmap); + +public: + imageClickableLabel(const QPixmap &pixmap, QWidget *parent = nullptr) : QLabel(parent), pixmap(pixmap){} + +protected: + void mousePressEvent(QMouseEvent *event) override + { + Q_UNUSED(event); + emit labelClicked(pixmap); + } + +private: + QPixmap pixmap; +}; + + +class kpAIDrawingBar : public QDockWidget +{ + Q_OBJECT + +signals: + void imageClicked(const QPixmap &pixmap); + +public: + kpAIDrawingBar(QWidget *parent); + ~kpAIDrawingBar(); + +public: + void initUI(); + bool getConfigStatus(); + void getconfigVersionData(); + void loginConfigurationPage(); + void setAiPixmap(QPixmap pixmap,int imageIndex, QGridLayout *pageLayout); + void updatePageLabel(); + + QSize getImageLabelSize(); + + bool eventFilter(QObject *watched, QEvent *event); + void handleLabelClicked(QObject *clickedObject); + + QPixmap createPixmapWithText(const QString &text); + QPixmap AIGeneratesErrorHandling(int errorCode); + +private slots: + void onConfigButtonClicked(); //配置按钮回调函数 + void onConfigSettingsChange(const QString &key); //AI配置成功后回调 + void onGenerateButtonClicked(); //生成按钮回调函数 + void handleInputTextChanged(); //文字变化回调函数 + + void showPreviousPage(); //显示上一页 + void showNextPage(); //显示下一页 + void handleLabelClick(const QPixmap &pixmap); + + void addPageAndStoreImages(); + void onStyleMoreButtonClick(); + + void startThread() { + // 启动线程 + aiThread.setAIData(textBox, AIImageSize, multipleNum, quantityNum, ImageStyle); + aiThread.start(); + } + void onThreadFinished(bool flag, QPixmap pixmap, int imageIndex, int imageSum, int errorCode); + +private: + void updateImageGrid(); + void deleteImageGridWidget(); + + void addRatioButtons(QGridLayout *layout, QString name, int line); + void addQuantityButtons(QGridLayout *layout); + void addMultipleButton(QGridLayout *layout, QString name, int line); + + QWidget *addAllStyleLabel(QString iconPath, QString labelText, int line); + QWidget *addStyleLabel(QString iconPath, QString labelText, int line); + + void addStyleWidget(); + void addStyleGrid(QWidget *widget, int line); + +private: + int quantityNum = 4; //数量按钮 + int ratioNum = 0; //比例按钮 + int multipleNum = 1; //倍数按钮 + int imageColumn = 2;//显示列表列数 + int currentPageIndx = 0;//切换页第几页 + + bool styleFlag; //风格标志位,用于判断按下哪一个风格 + bool buildButtonFlag; //生成按钮是否打开 + + QGSettings *AiSettings; //监听配置信息 + QSize AIImageSize; //图片大小 + QMovie *movie = nullptr;//生成等待图标 + QLabel *resultLabel; //生成结果 label + QLabel *pageLabel; //第几页面label + + QLabel *selectedIconLabel;//风格图片选择Label + QLabel *selectedTextLabel;//风格文字选择Label + + QWidget *configWidget; //立即配置页面 + QWidget *widget_low_poly; //多边形风格 + + QString textBox; //图像描述文字 + QString colorfulButtonStyle; //立即生成按钮渐变色 + QString colorGrayButtonStyle;//立即生成按钮置灰 + + QBoxLayout *vbox; //页面布局 + QHBoxLayout *resultGrid; //生成结果布局 + QGridLayout *styleGrid; //风格布局 + QPushButton *moreButton; //更多按钮 + + QScrollArea *scrollArea; //滚动窗口 + QPushButton *buildButton; //立即生成按钮 + + QButtonGroup *ratioButtonGroup; //比例按钮 + QButtonGroup *quantityButtonGroup; //数量按钮 + QButtonGroup *multipleButtonGroup; //倍数按钮 + + + QStackedWidget *stackedWidget; //生成结果的换页窗口 + QVector> imagesVector; //生成图像数据集成 + + VisionImageStyle ImageStyle; //风格样式 + AIModeDataThread aiThread; //线程类 + +}; +#endif