diff --git a/CMakeLists.txt b/CMakeLists.txt index b275e55..d32ecd8 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -64,8 +64,20 @@ 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}) + +pkg_check_modules(Jsoncpp REQUIRED jsoncpp) +include_directories(${Jsoncpp_INCLUDE_DIRS}) + +pkg_check_modules(JsonGlib REQUIRED json-glib-1.0) +include_directories(${JsonGlib_INCLUDE_DIRS}) + ## Generate header with version number ecm_setup_version(${RELEASE_SERVICE_VERSION} VARIABLE_PREFIX KOLOURPAINT @@ -308,6 +320,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 +358,13 @@ 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} + ${Jsoncpp_LIBRARIES} + ${JsonGlib_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..d8eaae5 100644 --- a/debian/control +++ b/debian/control @@ -18,6 +18,10 @@ 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, + libjsoncpp-dev, + libjson-glib-dev, Standards-Version: 4.6.1 Rules-Requires-Root: no Homepage: https://apps.kde.org/en/kolourpaint @@ -27,7 +31,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}, kylin-aiassistant 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..f7522df 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,123 @@ 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 "参数错误" + +msgid "Image resolution" +msgstr "图像分辨率" diff --git a/widgets/toolbars/kpAiDrawingBar.cpp b/widgets/toolbars/kpAiDrawingBar.cpp new file mode 100644 index 0000000..91cf3be --- /dev/null +++ b/widgets/toolbars/kpAiDrawingBar.cpp @@ -0,0 +1,1235 @@ +/* + 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); + + AiSettings = nullptr; + //取消登录界面绘画 + /* + if(!getConfigStatus()) + loginConfigurationPage(); + else + */ + + m_AiMode = new AIModeDataThread(); + if(m_AiMode->setSessionStatus()) + { + mSession = m_AiMode->getVisionSession(); + } + + initUI(); + + setFixedWidth(250); +} + +kpAIDrawingBar::~kpAIDrawingBar() +{ + if (AiSettings) + delete AiSettings; + if (m_AiMode) + delete m_AiMode; +} + +/** + * @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(512, 512); +// 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(); + + /* 图像分辨率 */ + auto *resolutionLabel = new QLabel(i18n("Image resolution")); + resolutionLabel->setAlignment(Qt::AlignLeft | Qt::AlignTop); + resolutionLabel->setFixedSize(180, 30); + + resolutionComboBox = new QComboBox(this); + addResolutionComboBox(); + + /* 生成数量布局 */ + QLabel *quantityLabel = new QLabel(i18n("Generated quantity")); + quantityLabel->setAlignment(Qt::AlignLeft | Qt::AlignTop); + quantityLabel->setFixedSize(180, 30); + + quantityComboBox = new QComboBox(this); + addQuantityComboBox(); + + /* 立即生成按钮 */ + 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); + deleteButton = new QPushButton(this); + resultLabel->setFixedSize(80,30); + + previousButton->setIcon(QIcon::fromTheme("ukui-start-symbolic")); + previousButton->setFixedSize(20,20); + previousButton->setStyleSheet("QPushButton { background-color: transparent; }"); + + pageLabel->setFixedSize(50,30); + pageLabel->setAlignment(Qt::AlignCenter); + + nextButton->setFixedSize(20,20); + nextButton->setIcon(QIcon::fromTheme("ukui-end-symbolic")); + nextButton->setStyleSheet("QPushButton { background-color: transparent; }"); + + deleteButton->setIcon(QIcon::fromTheme("edit-delete-symbolic")); + deleteButton->setFixedSize(24,24); + deleteButton->setStyleSheet("QPushButton { background-color: transparent; }"); + + resultGrid->addWidget(resultLabel); + resultGrid->addStretch(); + resultGrid->addWidget(previousButton); + resultGrid->addWidget(pageLabel); + resultGrid->addWidget(nextButton); + resultGrid->addWidget(deleteButton); + 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(resolutionLabel); + vbox->addWidget(resolutionComboBox); + vbox->addSpacing(15); + vbox->addWidget(quantityLabel); + vbox->addWidget(quantityComboBox); + 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(deleteButton, &QPushButton::clicked, this, &kpAIDrawingBar::deleteCurrentPage); + connect(m_AiMode, &AIModeDataThread::finishedSignal, this, &kpAIDrawingBar::onThreadFinished); + + centralWidget->setFixedWidth(240); + + 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-baroque", "style-surrealism", "style-watercolour", //头部删除"style-lolita" + "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, 1,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, 16); + 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(); + if (identifier > 9){ + identifier += 1; + } + ImageStyle = (VisionImageStyle)identifier; +} + +QJsonArray kpAIDrawingBar::readResolutionsFromJson(QString key) +{ + if (!mSession) + return QJsonArray(); + + QString jsonString = QString(vision_get_prompt2image_supported_params(mSession)); + + qDebug()<<"jsonString === "<addItem("512x512"); + return; + } + + for (const QJsonValue &value : resolutions) { + QString resolution = value.toString(); + resolutionComboBox->addItem(resolution); + } + + connect(resolutionComboBox, QOverload::of(&QComboBox::currentIndexChanged), + [=](int index) { + QString selectedResolution = resolutionComboBox->currentText(); + // 解析为QSize(这里假设分辨率总是"WxH"格式) + int widthPos = selectedResolution.indexOf('x'); + qDebug()<<"index = "<addItem("1张"); + } + else if (num == 6){ + quantityComboBox->addItem("1张"); + quantityComboBox->addItem("2张"); + quantityComboBox->addItem("6张"); + } + else if (num == 8){ + for (int i = 1; i <= num; i *= 2) { + quantityComboBox->addItem(QString("%1张").arg(i)); + } + } + else { + quantityComboBox->addItem("1张"); + qDebug()<<"读取生成数量不是常用数量, num = "<::of(&QComboBox::currentIndexChanged), + [=](int index) { + QString selectedResolution = quantityComboBox->currentText(); + QString numberString = selectedResolution.remove(QRegExp("[^\\d]")); + quantityNum = numberString.toInt(); + qDebug()<<"生成数量quantityNum = "<(findChild())->toPlainText(); + if(!resultText.isEmpty()) + textBox = resultText; + + qDebug() << "输入文字为:" << textBox; + + buildButton->setEnabled(false); + buildButton->setText(i18n("In formation...")); + buildButton->setStyleSheet(colorGrayButtonStyle); + buildButtonFlag = true; + if(!deleteButton->isEnabled()) + deleteButton->setEnabled(true); + + // 更新结果显示 + updateResultGrid(); + + // 更新图像 + 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 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); + if(show_quantityNum == 1){ + pageLayout->setAlignment(Qt::AlignTop | Qt::AlignLeft); + } + else { + 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; + size = getImageLabelSize(); + + QPixmap pixmap(size); + pixmap.fill(QColor("#E6E6E6")); + + QColor color("#B8B8B8"); + QPainter painter(&pixmap); + + // 设置字体和字体大小,这里假设使用默认字体,根据实际需求可自定义 + QFont font = painter.font(); + // 若需要调整字体大小以适应换行,请在此处设置,例如:font.setPointSize(10); + + // 计算文本在给定宽度下的自动换行字符串 + QString wrappedText = fontMetrics().elidedText(i18n(text.toLocal8Bit().data()), Qt::ElideNone, pixmap.rect().width(), Qt::TextWordWrap); + + painter.setPen(color); + painter.drawText(pixmap.rect(), Qt::AlignCenter | Qt::TextWordWrap, wrappedText); + painter.end(); + + qDebug()<<"Error message:"<setEnabled(true); + return; + } + if (imageIndex == 0){ + imagesVector.append(QVector()); + } + if (errorCode != 0) + map = AIGeneratesErrorHandling(errorCode); + else + map = pixmap; + + if (imagesVector.size() > 0 ){ + imagesVector.last().append(map); + } + qDebug()<<"onThreadFinished: imageIndex = "<setStyleSheet(colorfulButtonStyle);//设置立即生成按钮为立即生成 + buildButtonFlag = false; + addPageAndStoreImages(); + } +} + + +AIModeDataThread::AIModeDataThread() +{ + +} + +AIModeDataThread::~AIModeDataThread() +{ + vision_destory_session(session); +} + +bool AIModeDataThread::setSessionStatus() +{ + if (m_sessionFlag) + return true; + + session = nullptr; + VisionResult ret = vision_create_session(&session); + if (ret != VISION_SUCCESS) { + qDebug()<<"创建失败VisionResult="<textBox; + if(imageData.index == 0) + emit AIMode->finishedSignal(false, map, imageData.index, imageData.total, imageData.error_code); + emit AIMode->finishedSignal(true, map, imageData.index, imageData.total, imageData.error_code); +} + +/** + * @brief AIModeDataThread::someFunctionInThread + * AI服务调用函数 + * @return + */ +bool AIModeDataThread::someFunctionInThread() +{ + int width = AIImageSize.width(); + int height = AIImageSize.height(); + + vision_set_prompt2image_number(session, quantityNum); + vision_set_prompt2image_size(session, width, height); + vision_set_prompt2image_callback(session, generateImageCallback, this); + vision_set_prompt2image_style(session, ImageStyle); + + VisionResult imageRet = vision_prompt2image_async(session, textBox.toLocal8Bit().data()); + + qDebug()<<"ImageStyle == "<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(); + } + setEnabledDeleteButton(); + 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(); + } + setEnabledDeleteButton(); + qDebug()<<"stackedWidget->count() = "<count()<<"currentPageIndx="<removeWidget(stackedWidget->currentWidget()); + updatePageLabel(); + if(stackedWidget->count() <= 1){ + updateResultGrid(); + if (currentPageIndx == -1) + deleteButton->setEnabled(false); + else + setEnabledDeleteButton(); + } + else { + setEnabledDeleteButton(); + } +} + +void kpAIDrawingBar::setEnabledDeleteButton() +{ + qDebug()<<"currentPageIndx == "<count() - 1){ + deleteButton->setEnabled(false); + } + else { + deleteButton->setEnabled(true); + } +} +void kpAIDrawingBar::updateResultGrid() +{ + qDebug()<<"updateResultGrid: stackedWidget->count() === "<count(); + // 显示resultGrid中的所有子控件 + for (int i = 0; i < resultGrid->count(); ++i) + { + QLayoutItem *item = resultGrid->itemAt(i);; + if (stackedWidget->count() < 1 && (i == 2 || i == 3 || i ==4)){ + if (item && item->widget()){ + item->widget()->setVisible(false); + } + continue; + } + if (item && item->widget()){ + item->widget()->setVisible(true); + } + } +} + +/** + * @brief kpAIDrawingBar::updateImageGrid + * 更新、等待QLabel相关界面,并开启线程运行 + */ +void kpAIDrawingBar::updateImageGrid() +{ + show_quantityNum = quantityNum; + showAIImageSize = AIImageSize; + + QSize labelSize = getImageLabelSize(); + + QWidget *newWidget = new QWidget(); + QGridLayout *pageLayout = new QGridLayout(newWidget); + + pageLayout->setMargin (2); + pageLayout->setSpacing (5); + if(show_quantityNum == 1){ + pageLayout->setAlignment(Qt::AlignTop | Qt::AlignLeft); + } + else { + 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(); + + deleteButtonFlag = false; + deleteButton->setEnabled(false); + + 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 +#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 QObject +{ + Q_OBJECT + +public: + AIModeDataThread(); + ~AIModeDataThread(); + + bool setSessionStatus(); + VisionSession getVisionSession(){ + return session; + } + bool someFunctionInThread(); + + void setAIData (QString str, QSize size, int quantity, VisionImageStyle Style){ + textBox = str; + AIImageSize = size; + quantityNum = quantity; + ImageStyle = Style; + } + +signals: + void finishedSignal(bool flag, QPixmap pixmap, int imageIndex, int imageSum, int errorCode); + +private: + 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 = 1; //数量按钮 + QSize AIImageSize; + QString textBox; + VisionImageStyle ImageStyle; + bool m_sessionFlag = false; + VisionSession session; +}; + +/** + * @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 deleteCurrentPage(); + void setEnabledDeleteButton(); + void handleLabelClick(const QPixmap &pixmap); + + void addPageAndStoreImages(); + void onStyleMoreButtonClick(); + + void startThread() { + if (m_AiMode->setSessionStatus()){ + m_AiMode->setAIData(textBox, AIImageSize, quantityNum, ImageStyle); + m_AiMode->someFunctionInThread(); + } + } + void onThreadFinished(bool flag, QPixmap pixmap, int imageIndex, int imageSum, int errorCode); + +private: + void updateImageGrid(); + void updateResultGrid(); + void deleteImageGridWidget(); + + void addResolutionComboBox(); + void addQuantityComboBox(); + + QJsonArray readResolutionsFromJson(QString key); + int readNumFromJson(QString key); + 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 imageColumn = 2;//显示列表列数 + int quantityNum = 1; //数量按钮 + int show_quantityNum = 1; //数量按钮 + int currentPageIndx = -1;//切换页第几页 + + bool styleFlag; //风格标志位,用于判断按下哪一个风格 + bool deleteButtonFlag = true; + bool buildButtonFlag; + + QGSettings *AiSettings; //监听配置信息 + QSize AIImageSize; //图片大小 + QSize showAIImageSize; + 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; //立即生成按钮 + QPushButton *deleteButton; //删除按钮 + + QComboBox *resolutionComboBox; //图像分辨率 + QComboBox *quantityComboBox; //生成数量 + + QStackedWidget *stackedWidget; //生成结果的换页窗口 + QVector> imagesVector; //生成图像数据集成 + + VisionSession mSession = nullptr; + VisionImageStyle ImageStyle; //风格样式 + AIModeDataThread *m_AiMode; //AI生成程序 + +}; +#endif